Index: clang/include/clang/Driver/ToolChain.h =================================================================== --- clang/include/clang/Driver/ToolChain.h +++ clang/include/clang/Driver/ToolChain.h @@ -13,7 +13,7 @@ #include "clang/Basic/LangOptions.h" #include "clang/Basic/Sanitizers.h" #include "clang/Driver/Action.h" -#include "clang/Driver/Multilib.h" +#include "clang/Driver/MultilibBuilder.h" #include "clang/Driver/Types.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/ArrayRef.h" @@ -58,6 +58,7 @@ class SanitizerArgs; class Tool; class XRayArgs; +struct DetectedMultilibs; /// Helper structure used to pass information extracted from clang executable /// name such as `i686-linux-android-g++`. @@ -237,6 +238,8 @@ llvm::vfs::FileSystem &getVFS() const; const llvm::Triple &getTriple() const { return Triple; } + static constexpr llvm::StringLiteral MultilibFilename = "multilib.yaml"; + /// Get the toolchain's aux triple, if it has one. /// /// Exactly what the aux triple represents depends on the toolchain, but for @@ -793,6 +796,11 @@ } return TT; } + + void findMultilibsFromYAML(StringRef MultilibPath, + const llvm::opt::ArgList &Args, + DetectedMultilibs &Result) const; + }; /// Set a ToolChain's effective triple. Reset it when the registration object Index: clang/lib/Driver/ToolChain.cpp =================================================================== --- clang/lib/Driver/ToolChain.cpp +++ clang/lib/Driver/ToolChain.cpp @@ -9,9 +9,11 @@ #include "clang/Driver/ToolChain.h" #include "ToolChains/Arch/AArch64.h" #include "ToolChains/Arch/ARM.h" +#include "ToolChains/Arch/RISCV.h" #include "ToolChains/Clang.h" #include "ToolChains/CommonArgs.h" #include "ToolChains/Flang.h" +#include "ToolChains/Gnu.h" #include "ToolChains/InterfaceStubs.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Sanitizers.h" @@ -40,6 +42,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/FileUtilities.h" #include "llvm/Support/Path.h" +#include "llvm/Support/RISCVISAInfo.h" #include "llvm/Support/VersionTuple.h" #include "llvm/Support/VirtualFileSystem.h" #include "llvm/TargetParser/AArch64TargetParser.h" @@ -48,6 +51,7 @@ #include #include #include +#include #include using namespace clang; @@ -240,26 +244,62 @@ } } +static void getRISCVMultilibFlags(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args, + Multilib::flags_list &Result) { + std::vector Features; + riscv::getRISCVTargetFeatures(D, Triple, Args, Features); + const auto UnifiedFeatures = tools::unifyTargetFeatures(Features); + llvm::DenseSet FeatureSet(UnifiedFeatures.begin(), + UnifiedFeatures.end()); + // Add all Extenstion features + for (StringRef Feature : Features) { + std::string FeatureStr = Feature.str(); + if (FeatureStr.front() != '+') + continue; + // get rid of +/- on Feature + if (RISCVISAInfo::isSupportedExtensionFeature(FeatureStr.substr(1))) + Result.push_back(FeatureStr); + } + + if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { + Result.push_back(std::string("-mabi=") + A->getValue()); + } else { + std::vector FeatureStrs; + for (StringRef Feature : Features) + FeatureStrs.push_back(Feature.str()); + unsigned XLen = Triple.isRISCV32() ? 32 : 64; + if (auto ISAInfo = RISCVISAInfo::parseFeatures(XLen, FeatureStrs)) { + std::string ABI = ISAInfo.get()->computeDefaultABI().str(); + Result.push_back(std::string("-mabi=") + ABI); + } + } +} + Multilib::flags_list ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const { using namespace clang::driver::options; std::vector Result; const llvm::Triple Triple(ComputeEffectiveClangTriple(Args)); - Result.push_back("--target=" + Triple.str()); switch (Triple.getArch()) { case llvm::Triple::aarch64: case llvm::Triple::aarch64_32: case llvm::Triple::aarch64_be: + Result.push_back("--target=" + Triple.str()); getAArch64MultilibFlags(D, Triple, Args, Result); break; case llvm::Triple::arm: case llvm::Triple::armeb: case llvm::Triple::thumb: case llvm::Triple::thumbeb: + Result.push_back("--target=" + Triple.str()); getARMMultilibFlags(D, Triple, Args, Result); break; + case llvm::Triple::riscv32: + case llvm::Triple::riscv64: + getRISCVMultilibFlags(D, Triple, Args, Result); default: break; } @@ -1499,3 +1539,24 @@ delete DAL; return nullptr; } + +void ToolChain::findMultilibsFromYAML(StringRef MultilibPath, + const llvm::opt::ArgList &Args, DetectedMultilibs &Result) const { + llvm::ErrorOr> MB = + getDriver().getVFS().getBufferForFile(MultilibPath); + if (!MB) + return; + Multilib::flags_list Flags = getMultilibFlags(Args); + llvm::ErrorOr ErrorOrMultilibSet = + MultilibSet::parseYaml(*MB.get()); + if (ErrorOrMultilibSet.getError()) + return; + Result.Multilibs = ErrorOrMultilibSet.get(); + if (Result.Multilibs.select(Flags, Result.SelectedMultilibs)) + return; + getDriver().Diag(clang::diag::warn_drv_missing_multilib) << llvm::join(Flags, " "); + std::stringstream ss; + for (const Multilib &Multilib : Result.Multilibs) + ss << "\n" << llvm::join(Multilib.flags(), " "); + getDriver().Diag(clang::diag::note_drv_available_multilibs) << ss.str(); +} Index: clang/lib/Driver/ToolChains/BareMetal.cpp =================================================================== --- clang/lib/Driver/ToolChains/BareMetal.cpp +++ clang/lib/Driver/ToolChains/BareMetal.cpp @@ -161,30 +161,6 @@ return Triple.getEnvironmentName() == "elf"; } -static void findMultilibsFromYAML(const ToolChain &TC, const Driver &D, - StringRef MultilibPath, const ArgList &Args, - DetectedMultilibs &Result) { - llvm::ErrorOr> MB = - D.getVFS().getBufferForFile(MultilibPath); - if (!MB) - return; - Multilib::flags_list Flags = TC.getMultilibFlags(Args); - llvm::ErrorOr ErrorOrMultilibSet = - MultilibSet::parseYaml(*MB.get()); - if (ErrorOrMultilibSet.getError()) - return; - Result.Multilibs = ErrorOrMultilibSet.get(); - if (Result.Multilibs.select(Flags, Result.SelectedMultilibs)) - return; - D.Diag(clang::diag::warn_drv_missing_multilib) << llvm::join(Flags, " "); - std::stringstream ss; - for (const Multilib &Multilib : Result.Multilibs) - ss << "\n" << llvm::join(Multilib.flags(), " "); - D.Diag(clang::diag::note_drv_available_multilibs) << ss.str(); -} - -static constexpr llvm::StringLiteral MultilibFilename = "multilib.yaml"; - // Get the sysroot, before multilib takes effect. static std::string computeBaseSysRoot(const Driver &D, const llvm::Triple &Triple) { @@ -195,7 +171,7 @@ llvm::sys::path::append(SysRootDir, "..", "lib", "clang-runtimes"); SmallString<128> MultilibPath(SysRootDir); - llvm::sys::path::append(MultilibPath, MultilibFilename); + llvm::sys::path::append(MultilibPath, ToolChain::MultilibFilename); // New behaviour: if multilib.yaml is found then use clang-runtimes as the // sysroot. @@ -217,8 +193,8 @@ } } else { llvm::SmallString<128> MultilibPath(computeBaseSysRoot(D, Triple)); - llvm::sys::path::append(MultilibPath, MultilibFilename); - findMultilibsFromYAML(*this, D, MultilibPath, Args, Result); + llvm::sys::path::append(MultilibPath, ToolChain::MultilibFilename); + findMultilibsFromYAML(MultilibPath, Args, Result); SelectedMultilibs = Result.SelectedMultilibs; Multilibs = Result.Multilibs; } Index: clang/lib/Driver/ToolChains/Gnu.h =================================================================== --- clang/lib/Driver/ToolChains/Gnu.h +++ clang/lib/Driver/ToolChains/Gnu.h @@ -193,6 +193,7 @@ bool IsValid; llvm::Triple GCCTriple; const Driver &D; + const ToolChain &TC; // FIXME: These might be better as path objects. std::string GCCInstallPath; @@ -217,7 +218,8 @@ const std::string GentooConfigDir = "/etc/env.d/gcc"; public: - explicit GCCInstallationDetector(const Driver &D) : IsValid(false), D(D) {} + explicit GCCInstallationDetector(const Driver &D, const + ToolChain &TC) : IsValid(false), D(D), TC(TC) {} void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args, ArrayRef ExtraTripleAliases = std::nullopt); Index: clang/lib/Driver/ToolChains/Gnu.cpp =================================================================== --- clang/lib/Driver/ToolChains/Gnu.cpp +++ clang/lib/Driver/ToolChains/Gnu.cpp @@ -1750,7 +1750,37 @@ static void findRISCVBareMetalMultilibs(const Driver &D, const llvm::Triple &TargetTriple, StringRef Path, const ArgList &Args, - DetectedMultilibs &Result) { + DetectedMultilibs &Result, + const ToolChain &TC) { + auto FilePathsCallback = [](const Multilib &M) { + return std::vector( + {M.gccSuffix(), "/../../../../riscv64-unknown-elf/lib" + M.gccSuffix(), + "/../../../../riscv32-unknown-elf/lib" + M.gccSuffix()}); + }; + + // Find multilib.yaml and use that if it exists + // The name of the sysroot can be either riscv32 or riscv64, so check both. + std::optional> ExistingMultilibYamlPath = std::nullopt; + SmallString<128> Toplevel(Path); + llvm::sys::path::append(Toplevel, "..", "..", "..", ".."); + SmallString<128> MultilibYamlPath32(Toplevel); + SmallString<128> MultilibYamlPath64(Toplevel); + + llvm::sys::path::append(MultilibYamlPath64, "riscv64-unknown-elf", "lib", + ToolChain::MultilibFilename); + llvm::sys::path::append(MultilibYamlPath32, "riscv32-unknown-elf", "lib", + ToolChain::MultilibFilename); + if (D.getVFS().exists(MultilibYamlPath64)) + ExistingMultilibYamlPath = MultilibYamlPath64; + else if (D.getVFS().exists(MultilibYamlPath32)) + ExistingMultilibYamlPath = MultilibYamlPath32; + + if (ExistingMultilibYamlPath) { + TC.findMultilibsFromYAML(ExistingMultilibYamlPath.value(), Args, Result); + Result.Multilibs.setFilePathsCallback(FilePathsCallback); + return; + } + FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS()); struct RiscvMultilib { StringRef march; @@ -1772,17 +1802,11 @@ .flag(Twine("-march=", Element.march).str()) .flag(Twine("-mabi=", Element.mabi).str())); } - MultilibSet RISCVMultilibs = - MultilibSetBuilder() - .Either(Ms) - .makeMultilibSet() - .FilterOut(NonExistent) - .setFilePathsCallback([](const Multilib &M) { - return std::vector( - {M.gccSuffix(), - "/../../../../riscv64-unknown-elf/lib" + M.gccSuffix(), - "/../../../../riscv32-unknown-elf/lib" + M.gccSuffix()}); - }); + MultilibSet RISCVMultilibs = MultilibSetBuilder() + .Either(Ms) + .makeMultilibSet() + .FilterOut(NonExistent) + .setFilePathsCallback(FilePathsCallback); Multilib::flags_list Flags; llvm::StringSet<> Added_ABIs; @@ -1804,9 +1828,10 @@ static void findRISCVMultilibs(const Driver &D, const llvm::Triple &TargetTriple, StringRef Path, - const ArgList &Args, DetectedMultilibs &Result) { + const ArgList &Args, DetectedMultilibs &Result, + const ToolChain &TC) { if (TargetTriple.getOS() == llvm::Triple::UnknownOS) - return findRISCVBareMetalMultilibs(D, TargetTriple, Path, Args, Result); + return findRISCVBareMetalMultilibs(D, TargetTriple, Path, Args, Result, TC); FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS()); MultilibBuilder Ilp32 = @@ -2708,7 +2733,7 @@ if (!findMIPSMultilibs(D, TargetTriple, Path, Args, Detected)) return false; } else if (TargetTriple.isRISCV()) { - findRISCVMultilibs(D, TargetTriple, Path, Args, Detected); + findRISCVMultilibs(D, TargetTriple, Path, Args, Detected, TC); } else if (isMSP430(TargetArch)) { findMSP430Multilibs(D, TargetTriple, Path, Args, Detected); } else if (TargetArch == llvm::Triple::avr) { @@ -2883,7 +2908,7 @@ Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) - : ToolChain(D, Triple, Args), GCCInstallation(D), + : ToolChain(D, Triple, Args), GCCInstallation(D, *this), CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) { getProgramPaths().push_back(getDriver().getInstalledDir()); if (getDriver().getInstalledDir() != getDriver().Dir) Index: clang/test/Driver/Inputs/multilib_riscv_elf_sdk_yaml/riscv64-unknown-elf/bin/ld =================================================================== --- /dev/null +++ clang/test/Driver/Inputs/multilib_riscv_elf_sdk_yaml/riscv64-unknown-elf/bin/ld @@ -0,0 +1 @@ +#!/bin/true Index: clang/test/Driver/Inputs/multilib_riscv_elf_sdk_yaml/riscv64-unknown-elf/lib/multilib.yaml =================================================================== --- /dev/null +++ clang/test/Driver/Inputs/multilib_riscv_elf_sdk_yaml/riscv64-unknown-elf/lib/multilib.yaml @@ -0,0 +1,46 @@ +--- +# How does clang use this file? +# 1. If the ToolChain class for the architecture supports this form of +# multilib it then it loads the file if present in sysroot. +# 2. Generate flags from the user provided arguments. +# (Use `clang -print-multi-flags-experimental` to see which flags are +# generated). +# 3. Compare the arguments against each regular expression and store +# associated flags if there's a match. +# 4. Find the last library variant whose flags are a subset of the +# flags derived from the user provided arguments. +# 5. Use the directory for the library variant as the sysroot. + +# Clang will emit an error if this number is greater than its current multilib +# version or if its major version differs, but will accept lesser minor +# versions. +MultilibVersion: 1.0 + +# A library is considered compatible if the are a subset of the flags derived +# from the arguments provided by the user. +# If multiple libraries are deemed compatible then the one that appears +# last in the list wins. +Variants: +- Dir: rv32i/ilp32 + Flags: [-mabi=ilp32] + +- Dir: rv32iac/ilp32 + Flags: [-mabi=ilp32, +a, +c] + +- Dir: rv32im/ilp32 + Flags: [-mabi=ilp32, +m] + +- Dir: rv32imac/ilp32 + Flags: [-mabi=ilp32, +m, +a, +c] + +- Dir: rv32imafc/ilp32f + Flags: [-mabi=ilp32f, +m, +a, +f, +c] + +- Dir: rv64imac/lp64 + Flags: [-mabi=lp64, +m, +a, +c] + +# GCC sysroots will have a default march/mabi sitting at the top level. Assume +# this is rv64imafdc/lp64d for this test. +- Dir: . + Flags: [-mabi=lp64d, +m, +a, +d, +c] +... Index: clang/test/Driver/riscv-toolchain-multilib-yaml.c =================================================================== --- /dev/null +++ clang/test/Driver/riscv-toolchain-multilib-yaml.c @@ -0,0 +1,79 @@ +// UNSUPPORTED: system-windows +// In this test, multilib resolution is resolved using a multilib.yaml +// definition, in which multilibs are picked in accordance to matching abi / +// marchs. + +// RUN: env "PATH=" %clang -### %s -fuse-ld=ld \ +// RUN: --target=riscv32-unknown-elf --rtlib=platform --sysroot= \ +// RUN: -march=rv32iac -mabi=ilp32\ +// RUN: --gcc-toolchain=%S/Inputs/multilib_riscv_elf_sdk_yaml 2>&1 \ +// RUN: | FileCheck -check-prefix=C-RV32IAC-BAREMETAL-MULTI-ILP32 %s + +// C-RV32IAC-BAREMETAL-MULTI-ILP32: "{{.*}}/Inputs/multilib_riscv_elf_sdk_yaml/lib/gcc/riscv64-unknown-elf/8.2.0/../../..{{/|\\\\}}..{{/|\\\\}}riscv64-unknown-elf/lib/rv32iac/ilp32{{/|\\\\}}crt0.o" +// C-RV32IAC-BAREMETAL-MULTI-ILP32: "{{.*}}/Inputs/multilib_riscv_elf_sdk_yaml/lib/gcc/riscv64-unknown-elf/8.2.0/rv32iac/ilp32{{/|\\\\}}crtbegin.o" +// C-RV32IAC-BAREMETAL-MULTI-ILP32: "{{.*}}/Inputs/multilib_riscv_elf_sdk_yaml/lib/gcc/riscv64-unknown-elf/8.2.0/rv32iac/ilp32{{/|\\\\}}crtend.o" + +// RUN: env "PATH=" %clang -### %s -fuse-ld=ld \ +// RUN: --target=riscv32-unknown-elf --rtlib=platform --sysroot= \ +// RUN: -march=rv32imafc -mabi=ilp32f\ +// RUN: --gcc-toolchain=%S/Inputs/multilib_riscv_elf_sdk_yaml 2>&1 \ +// RUN: | FileCheck -check-prefix=C-RV32IMAFC-BAREMETAL-MULTI-ILP32F %s + +// C-RV32IMAFC-BAREMETAL-MULTI-ILP32F: "{{.*}}/Inputs/multilib_riscv_elf_sdk_yaml/lib/gcc/riscv64-unknown-elf/8.2.0/../../..{{/|\\\\}}..{{/|\\\\}}riscv64-unknown-elf/lib/rv32imafc/ilp32f{{/|\\\\}}crt0.o" +// C-RV32IMAFC-BAREMETAL-MULTI-ILP32F: "{{.*}}/Inputs/multilib_riscv_elf_sdk_yaml/lib/gcc/riscv64-unknown-elf/8.2.0/rv32imafc/ilp32f{{/|\\\\}}crtbegin.o" +// C-RV32IMAFC-BAREMETAL-MULTI-ILP32F: "{{.*}}/Inputs/multilib_riscv_elf_sdk_yaml/lib/gcc/riscv64-unknown-elf/8.2.0/rv32imafc/ilp32f{{/|\\\\}}crtend.o" + +// Check the addition of extensions for which we don't have an exact match of multilib +// RUN: env "PATH=" %clang -### %s -fuse-ld=ld \ +// RUN: --target=riscv32-unknown-elf --rtlib=platform --sysroot= \ +// RUN: -march=rv32imafc_zba -mabi=ilp32f\ +// RUN: --gcc-toolchain=%S/Inputs/multilib_riscv_elf_sdk_yaml 2>&1 \ +// RUN: | FileCheck -check-prefix=C-RV32IMAFC-ZBA-BAREMETAL-MULTI-ILP32F %s + +// C-RV32IMAFC-ZBA-BAREMETAL-MULTI-ILP32F: "{{.*}}/Inputs/multilib_riscv_elf_sdk_yaml/lib/gcc/riscv64-unknown-elf/8.2.0/../../..{{/|\\\\}}..{{/|\\\\}}riscv64-unknown-elf/lib/rv32imafc/ilp32f{{/|\\\\}}crt0.o" +// C-RV32IMAFC-ZBA-BAREMETAL-MULTI-ILP32F: "{{.*}}/Inputs/multilib_riscv_elf_sdk_yaml/lib/gcc/riscv64-unknown-elf/8.2.0/rv32imafc/ilp32f{{/|\\\\}}crtbegin.o" +// C-RV32IMAFC-ZBA-BAREMETAL-MULTI-ILP32F: "{{.*}}/Inputs/multilib_riscv_elf_sdk_yaml/lib/gcc/riscv64-unknown-elf/8.2.0/rv32imafc/ilp32f{{/|\\\\}}crtend.o" + +// RUN: env "PATH=" %clang -### %s -fuse-ld=ld \ +// RUN: --target=riscv64-unknown-elf --rtlib=platform --sysroot= \ +// RUN: -march=rv64imac_zba -mabi=lp64\ +// RUN: --gcc-toolchain=%S/Inputs/multilib_riscv_elf_sdk_yaml 2>&1 \ +// RUN: | FileCheck -check-prefix=C-RV64IMAC-ZBA-BAREMETAL-MULTI-LP64 %s + +// C-RV64IMAC-ZBA-BAREMETAL-MULTI-LP64: "{{.*}}/Inputs/multilib_riscv_elf_sdk_yaml/lib/gcc/riscv64-unknown-elf/8.2.0/../../..{{/|\\\\}}..{{/|\\\\}}riscv64-unknown-elf/lib/rv64imac/lp64{{/|\\\\}}crt0.o" +// C-RV64IMAC-ZBA-BAREMETAL-MULTI-LP64: "{{.*}}/Inputs/multilib_riscv_elf_sdk_yaml/lib/gcc/riscv64-unknown-elf/8.2.0/rv64imac/lp64{{/|\\\\}}crtbegin.o" +// C-RV64IMAC-ZBA-BAREMETAL-MULTI-LP64: "{{.*}}/Inputs/multilib_riscv_elf_sdk_yaml/lib/gcc/riscv64-unknown-elf/8.2.0/rv64imac/lp64{{/|\\\\}}crtend.o" + +// For this toolchain, rv64imafdc is considered the default toplevel multilib. Check this. +// RUN: env "PATH=" %clang -### %s -fuse-ld=ld \ +// RUN: --target=riscv64-unknown-elf --rtlib=platform --sysroot= \ +// RUN: -march=rv64imafdc -mabi=lp64d\ +// RUN: --gcc-toolchain=%S/Inputs/multilib_riscv_elf_sdk_yaml 2>&1 \ +// RUN: | FileCheck -check-prefix=C-RV64IMAFDC-BAREMETAL-MULTI-LP64D %s + +// Check default ABI is added +// RUN: env "PATH=" %clang -### %s -fuse-ld=ld \ +// RUN: --target=riscv64-unknown-elf --rtlib=platform --sysroot= \ +// RUN: -march=rv64imafdc \ +// RUN: --gcc-toolchain=%S/Inputs/multilib_riscv_elf_sdk_yaml 2>&1 \ +// RUN: | FileCheck -check-prefix=C-RV64IMAFDC-BAREMETAL-MULTI %s + +// C-RV64IMAFDC-BAREMETAL-MULTI: "{{.*}}/Inputs/multilib_riscv_elf_sdk_yaml/lib/gcc/riscv64-unknown-elf/8.2.0/../../..{{/|\\\\}}..{{/|\\\\}}riscv64-unknown-elf/lib{{/|\\\\}}crt0.o" +// C-RV64IMAFDC-BAREMETAL-MULTI: "{{.*}}/Inputs/multilib_riscv_elf_sdk_yaml/lib/gcc/riscv64-unknown-elf/8.2.0{{/|\\\\}}crtbegin.o" +// C-RV64IMAFDC-BAREMETAL-MULTI: "{{.*}}/Inputs/multilib_riscv_elf_sdk_yaml/lib/gcc/riscv64-unknown-elf/8.2.0{{/|\\\\}}crtend.o" + +// C-RV64IMAFDC-BAREMETAL-MULTI-LP64D: "{{.*}}/Inputs/multilib_riscv_elf_sdk_yaml/lib/gcc/riscv64-unknown-elf/8.2.0/../../..{{/|\\\\}}..{{/|\\\\}}riscv64-unknown-elf/lib{{/|\\\\}}crt0.o" +// C-RV64IMAFDC-BAREMETAL-MULTI-LP64D: "{{.*}}/Inputs/multilib_riscv_elf_sdk_yaml/lib/gcc/riscv64-unknown-elf/8.2.0{{/|\\\\}}crtbegin.o" +// C-RV64IMAFDC-BAREMETAL-MULTI-LP64D: "{{.*}}/Inputs/multilib_riscv_elf_sdk_yaml/lib/gcc/riscv64-unknown-elf/8.2.0{{/|\\\\}}crtend.o" + +// RUN: %clang -no-canonical-prefixes -print-multi-lib 2>&1 \ +// RUN: --target=riscv64-unknown-elf --sysroot= \ +// RUN: --gcc-toolchain=%S/Inputs/multilib_riscv_elf_sdk_yaml 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-PRINT-MULTI-LIB %s +// CHECK-PRINT-MULTI-LIB: rv32i/ilp32;@mabi=ilp32 +// CHECK-PRINT-MULTI-LIB: rv32iac/ilp32;@mabi=ilp32 +// CHECK-PRINT-MULTI-LIB: rv32im/ilp32;@mabi=ilp32 +// CHECK-PRINT-MULTI-LIB: rv32imac/ilp32;@mabi=ilp32 +// CHECK-PRINT-MULTI-LIB: rv32imafc/ilp32f;@mabi=ilp32f +// CHECK-PRINT-MULTI-LIB: rv64imac/lp64;@mabi=lp64 +// CHECK-PRINT-MULTI-LIB: .;@mabi=lp64d