diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index fb5d38ab4202..54b0770fefbf 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -2153,6 +2153,11 @@ void Driver::generatePrefixedToolNames( // FIXME: Needs a better variable than DefaultTargetTriple Names.emplace_back(DefaultTargetTriple + "-" + Tool); Names.emplace_back(Tool); + + // Allow the discovery of tools prefixed with LLVM's default target triple. + std::string LLVMDefaultTargetTriple = llvm::sys::getDefaultTargetTriple(); + if (LLVMDefaultTargetTriple != DefaultTargetTriple) + Names.emplace_back(LLVMDefaultTargetTriple + "-" + Tool); } static bool ScanDirForExecutable(SmallString<128> &Dir, @@ -2248,6 +2253,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, case llvm::Triple::Linux: if (Target.getArch() == llvm::Triple::hexagon) TC = new toolchains::HexagonToolChain(*this, Target, Args); + else if ((Target.getVendor() == llvm::Triple::MipsTechnologies) && + !Target.hasEnvironment()) + TC = new toolchains::MipsLLVMToolChain(*this, Target, Args); else TC = new toolchains::Linux(*this, Target, Args); break; diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index ec62fba566c4..09b77e74e7d0 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -333,7 +333,6 @@ Tool *ToolChain::SelectTool(const JobAction &JA) const { std::string ToolChain::GetFilePath(const char *Name) const { return D.GetFilePath(Name, *this); - } std::string ToolChain::GetProgramPath(const char *Name) const { diff --git a/clang/lib/Driver/ToolChains.cpp b/clang/lib/Driver/ToolChains.cpp index e18656cb3df3..97f17cf1b17d 100644 --- a/clang/lib/Driver/ToolChains.cpp +++ b/clang/lib/Driver/ToolChains.cpp @@ -1294,8 +1294,9 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const { "i586-linux-gnu"}; static const char *const MIPSLibDirs[] = {"/lib"}; - static const char *const MIPSTriples[] = { - "mips-linux-gnu", "mips-mti-linux-gnu", "mips-img-linux-gnu"}; + static const char *const MIPSTriples[] = {"mips-linux-gnu", "mips-mti-linux", + "mips-mti-linux-gnu", + "mips-img-linux-gnu"}; static const char *const MIPSELLibDirs[] = {"/lib"}; static const char *const MIPSELTriples[] = { "mipsel-linux-gnu", "mipsel-linux-android", "mips-img-linux-gnu"}; @@ -1686,6 +1687,32 @@ static bool findMIPSMultilibs(const Driver &D, const llvm::Triple &TargetTriple, }); } + // Check for Musl toolchain multilibs + MultilibSet MuslMipsMultilibs; + { + auto MArchMipsR2 = makeMultilib("") + .osSuffix("/mips-r2-hard-musl") + .flag("+EB") + .flag("-EL") + .flag("+march=mips32r2"); + + auto MArchMipselR2 = makeMultilib("/mipsel-r2-hard-musl") + .flag("-EB") + .flag("+EL") + .flag("+march=mips32r2"); + + MuslMipsMultilibs = MultilibSet().Either(MArchMipsR2, MArchMipselR2); + + // Specify the callback that computes the include directories. + MuslMipsMultilibs.setIncludeDirsCallback([]( + StringRef InstallDir, StringRef TripleStr, const Multilib &M) { + std::vector Dirs; + Dirs.push_back( + (InstallDir + "/../sysroot" + M.osSuffix() + "/usr/include").str()); + return Dirs; + }); + } + // Check for Code Sourcery toolchain multilibs MultilibSet CSMipsMultilibs; { @@ -1831,6 +1858,16 @@ static bool findMIPSMultilibs(const Driver &D, const llvm::Triple &TargetTriple, return false; } + if (TargetTriple.getVendor() == llvm::Triple::MipsTechnologies && + TargetTriple.getOS() == llvm::Triple::Linux && + TargetTriple.getEnvironment() == llvm::Triple::UnknownEnvironment) { + if (MuslMipsMultilibs.select(Flags, Result.SelectedMultilib)) { + Result.Multilibs = MuslMipsMultilibs; + return true; + } + return false; + } + if (TargetTriple.getVendor() == llvm::Triple::ImaginationTechnologies && TargetTriple.getOS() == llvm::Triple::Linux && TargetTriple.getEnvironment() == llvm::Triple::GNU) { @@ -2208,13 +2245,135 @@ void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs, getTriple().getArch() == llvm::Triple::aarch64_be || (getTriple().getOS() == llvm::Triple::Linux && (!V.isOlderThan(4, 7, 0) || getTriple().isAndroid())) || - getTriple().getOS() == llvm::Triple::NaCl; + getTriple().getOS() == llvm::Triple::NaCl || + (getTriple().getVendor() == llvm::Triple::MipsTechnologies && + !getTriple().hasEnvironment()); if (DriverArgs.hasFlag(options::OPT_fuse_init_array, options::OPT_fno_use_init_array, UseInitArrayDefault)) CC1Args.push_back("-fuse-init-array"); } +/// Mips Toolchain +MipsLLVMToolChain::MipsLLVMToolChain(const Driver &D, + const llvm::Triple &Triple, + const ArgList &Args) + : Linux(D, Triple, Args) { + // Select the correct multilib according to the given arguments. + DetectedMultilibs Result; + findMIPSMultilibs(D, Triple, "", Args, Result); + Multilibs = Result.Multilibs; + SelectedMultilib = Result.SelectedMultilib; + + // Find out the library suffix based on the ABI. + LibSuffix = tools::mips::getMipsABILibSuffix(Args, Triple); + getFilePaths().clear(); + getFilePaths().push_back(computeSysRoot() + "/usr/lib" + LibSuffix); + + // Use LLD by default. + if (!Args.getLastArg(options::OPT_fuse_ld_EQ)) + Linker = GetProgramPath("lld"); +} + +void MipsLLVMToolChain::AddClangSystemIncludeArgs( + const ArgList &DriverArgs, ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdinc)) + return; + + const Driver &D = getDriver(); + + if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { + SmallString<128> P(D.ResourceDir); + llvm::sys::path::append(P, "include"); + addSystemInclude(DriverArgs, CC1Args, P); + } + + if (DriverArgs.hasArg(options::OPT_nostdlibinc)) + return; + + const auto &Callback = Multilibs.includeDirsCallback(); + if (Callback) { + const auto IncludePaths = + Callback(D.getInstalledDir(), getTripleString(), SelectedMultilib); + for (const auto &Path : IncludePaths) + addExternCSystemIncludeIfExists(DriverArgs, CC1Args, Path); + } +} + +Tool *MipsLLVMToolChain::buildLinker() const { + return new tools::gnutools::Linker(*this); +} + +std::string MipsLLVMToolChain::computeSysRoot() const { + if (!getDriver().SysRoot.empty()) + return getDriver().SysRoot + SelectedMultilib.osSuffix(); + + const std::string InstalledDir(getDriver().getInstalledDir()); + std::string SysRootPath = + InstalledDir + "/../sysroot" + SelectedMultilib.osSuffix(); + if (llvm::sys::fs::exists(SysRootPath)) + return SysRootPath; + + return std::string(); +} + +ToolChain::CXXStdlibType +MipsLLVMToolChain::GetCXXStdlibType(const ArgList &Args) const { + Arg *A = Args.getLastArg(options::OPT_stdlib_EQ); + if (A) { + StringRef Value = A->getValue(); + if (Value != "libc++") + getDriver().Diag(diag::err_drv_invalid_stdlib_name) + << A->getAsString(Args); + } + + return ToolChain::CST_Libcxx; +} + +void MipsLLVMToolChain::AddClangCXXStdlibIncludeArgs( + const ArgList &DriverArgs, ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdlibinc) || + DriverArgs.hasArg(options::OPT_nostdincxx)) + return; + + assert((GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx) && + "Only -lc++ (aka libcxx) is suported in this toolchain."); + + const auto &Callback = Multilibs.includeDirsCallback(); + if (Callback) { + const auto IncludePaths = Callback(getDriver().getInstalledDir(), + getTripleString(), SelectedMultilib); + for (const auto &Path : IncludePaths) { + if (llvm::sys::fs::exists(Path + "/c++/v1")) { + addSystemInclude(DriverArgs, CC1Args, Path + "/c++/v1"); + break; + } + } + } +} + +void MipsLLVMToolChain::AddCXXStdlibLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + assert((GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) && + "Only -lc++ (aka libxx) is suported in this toolchain."); + + CmdArgs.push_back("-lc++"); + CmdArgs.push_back("-lc++abi"); + CmdArgs.push_back("-lunwind"); +} + +std::string MipsLLVMToolChain::getCompilerRT(const ArgList &Args, + StringRef Component, + bool Shared) const { + SmallString<128> Path(getDriver().ResourceDir); + llvm::sys::path::append(Path, SelectedMultilib.osSuffix(), "lib" + LibSuffix, + getOS()); + llvm::sys::path::append(Path, Twine("libclang_rt." + Component + "-" + + getTriple().getArchName() + + (Shared ? ".so" : ".a"))); + return Path.str(); +} + /// Hexagon Toolchain std::string HexagonToolChain::GetGnuDir(const std::string &InstalledDir, diff --git a/clang/lib/Driver/ToolChains.h b/clang/lib/Driver/ToolChains.h index 4d25a3ba9fbd..a613d093cdbb 100644 --- a/clang/lib/Driver/ToolChains.h +++ b/clang/lib/Driver/ToolChains.h @@ -746,6 +746,7 @@ public: SanitizerMask getSupportedSanitizers() const override; void addProfileRTLibs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const override; + virtual std::string computeSysRoot() const; std::string Linker; std::vector ExtraOpts; @@ -753,9 +754,6 @@ public: protected: Tool *buildAssembler() const override; Tool *buildLinker() const override; - -private: - std::string computeSysRoot() const; }; class LLVM_LIBRARY_VISIBILITY CudaToolChain : public Linux { @@ -770,6 +768,42 @@ public: llvm::opt::ArgStringList &CC1Args) const override; }; +class LLVM_LIBRARY_VISIBILITY MipsLLVMToolChain : public Linux { +protected: + Tool *buildLinker() const override; + +public: + MipsLLVMToolChain(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args); + + void + AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + + CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override; + + void AddClangCXXStdlibIncludeArgs( + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + + void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const override; + + std::string getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component, + bool Shared = false) const override; + + std::string computeSysRoot() const override; + + RuntimeLibType GetDefaultRuntimeLibType() const override { + return GCCInstallation.isValid() ? RuntimeLibType::RLT_Libgcc + : RuntimeLibType::RLT_CompilerRT; + } + +private: + Multilib SelectedMultilib; + std::string LibSuffix; +}; + class LLVM_LIBRARY_VISIBILITY HexagonToolChain : public Linux { protected: GCCVersion GCCLibAndIncVersion; diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index 3e4cb3144f2a..dc11316cdcdc 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -1078,6 +1078,16 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple, // FIXME: Warn on inconsistent use of -march and -mabi. } +std::string mips::getMipsABILibSuffix(const ArgList &Args, + const llvm::Triple &Triple) { + StringRef CPUName, ABIName; + tools::mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName); + return llvm::StringSwitch(ABIName) + .Case("o32", "") + .Case("n32", "32") + .Case("n64", "64"); +} + // Convert ABI name to the GNU tools acceptable variant. static StringRef getGnuCompatibleMipsABIName(StringRef ABI) { return llvm::StringSwitch(ABI) @@ -4643,12 +4653,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } // -fuse-cxa-atexit is default. - if (!Args.hasFlag(options::OPT_fuse_cxa_atexit, - options::OPT_fno_use_cxa_atexit, - !IsWindowsCygnus && !IsWindowsGNU && - getToolChain().getTriple().getOS() != llvm::Triple::Solaris && - getToolChain().getArch() != llvm::Triple::hexagon && - getToolChain().getArch() != llvm::Triple::xcore) || + if (!Args.hasFlag( + options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit, + !IsWindowsCygnus && !IsWindowsGNU && + getToolChain().getTriple().getOS() != llvm::Triple::Solaris && + getToolChain().getArch() != llvm::Triple::hexagon && + getToolChain().getArch() != llvm::Triple::xcore && + ((getToolChain().getTriple().getVendor() != + llvm::Triple::MipsTechnologies) || + getToolChain().getTriple().hasEnvironment())) || KernelOrKext) CmdArgs.push_back("-fno-use-cxa-atexit"); @@ -8250,20 +8263,17 @@ static std::string getLinuxDynamicLinker(const ArgList &Args, return "/lib/ld-linux.so.3"; } else if (Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel || Arch == llvm::Triple::mips64 || Arch == llvm::Triple::mips64el) { - StringRef CPUName; - StringRef ABIName; - mips::getMipsCPUAndABI(Args, ToolChain.getTriple(), CPUName, ABIName); - bool IsNaN2008 = mips::isNaN2008(Args, ToolChain.getTriple()); - - StringRef LibDir = llvm::StringSwitch(ABIName) - .Case("o32", "/lib") - .Case("n32", "/lib32") - .Case("n64", "/lib64") - .Default("/lib"); + std::string LibDir = + "/lib" + mips::getMipsABILibSuffix(Args, ToolChain.getTriple()); StringRef LibName; + bool IsNaN2008 = mips::isNaN2008(Args, ToolChain.getTriple()); if (mips::isUCLibc(Args)) LibName = IsNaN2008 ? "ld-uClibc-mipsn8.so.0" : "ld-uClibc.so.0"; - else + else if (!ToolChain.getTriple().hasEnvironment()) { + bool LE = (ToolChain.getTriple().getArch() == llvm::Triple::mipsel) || + (ToolChain.getTriple().getArch() == llvm::Triple::mips64el); + LibName = LE ? "ld-musl-mipsel.so.1" : "ld-musl-mips.so.1"; + } else LibName = IsNaN2008 ? "ld-linux-mipsn8.so.1" : "ld.so.1"; return (LibDir + "/" + LibName).str(); @@ -8375,6 +8385,9 @@ void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, const bool IsPIE = !Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_static) && (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault()); + const bool HasCRTBeginEndFiles = + ToolChain.getTriple().hasEnvironment() || + (ToolChain.getTriple().getVendor() != llvm::Triple::MipsTechnologies); ArgStringList CmdArgs; @@ -8386,6 +8399,13 @@ void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, // handled somewhere else. Args.ClaimAllArgs(options::OPT_w); + if (llvm::sys::path::filename(ToolChain.Linker) == "lld") { + CmdArgs.push_back("-flavor"); + CmdArgs.push_back("gnu"); + CmdArgs.push_back("-target"); + CmdArgs.push_back(Args.MakeArgString(getToolChain().getTripleString())); + } + if (!D.SysRoot.empty()) CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); @@ -8460,7 +8480,9 @@ void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbeginS.o"; else crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbegin.o"; - CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin))); + + if (HasCRTBeginEndFiles) + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin))); // Add crtfastmath.o if available and fast math is enabled. ToolChain.AddFastMathRuntimeIfAvailable(Args, CmdArgs); @@ -8559,11 +8581,13 @@ void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, else crtend = isAndroid ? "crtend_android.o" : "crtend.o"; - CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend))); + if (HasCRTBeginEndFiles) + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend))); if (!isAndroid) CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); } - } + } else if (Args.hasArg(options::OPT_rtlib_EQ)) + AddRunTimeLibs(ToolChain, D, CmdArgs, Args); C.addCommand(llvm::make_unique(JA, *this, ToolChain.Linker.c_str(), CmdArgs, Inputs)); diff --git a/clang/lib/Driver/Tools.h b/clang/lib/Driver/Tools.h index be306e358fa7..7e4fc6a0b481 100644 --- a/clang/lib/Driver/Tools.h +++ b/clang/lib/Driver/Tools.h @@ -270,6 +270,8 @@ NanEncoding getSupportedNanEncoding(StringRef &CPU); void getMipsCPUAndABI(const llvm::opt::ArgList &Args, const llvm::Triple &Triple, StringRef &CPUName, StringRef &ABIName); +std::string getMipsABILibSuffix(const llvm::opt::ArgList &Args, + const llvm::Triple &Triple); bool hasMipsAbiArg(const llvm::opt::ArgList &Args, const char *Value); bool isUCLibc(const llvm::opt::ArgList &Args); bool isNaN2008(const llvm::opt::ArgList &Args, const llvm::Triple &Triple); diff --git a/clang/test/Driver/Inputs/mips_mti_linux/lib/clang/3.8.0/mips-r2-hard-musl/lib/linux/libclang_rt.builtins-mips.a b/clang/test/Driver/Inputs/mips_mti_linux/lib/clang/3.8.0/mips-r2-hard-musl/lib/linux/libclang_rt.builtins-mips.a new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/clang/test/Driver/Inputs/mips_mti_linux/lib/clang/3.8.0/mips-r2-hard-musl/lib/linux/libclang_rt.builtins-mips.so b/clang/test/Driver/Inputs/mips_mti_linux/lib/clang/3.8.0/mips-r2-hard-musl/lib/linux/libclang_rt.builtins-mips.so new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/clang/test/Driver/Inputs/mips_mti_linux/lib/clang/3.8.0/mipsel-r2-hard-musl/lib/linux/libclang_rt.builtins-mipsel.a b/clang/test/Driver/Inputs/mips_mti_linux/lib/clang/3.8.0/mipsel-r2-hard-musl/lib/linux/libclang_rt.builtins-mipsel.a new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/clang/test/Driver/Inputs/mips_mti_linux/lib/clang/3.8.0/mipsel-r2-hard-musl/lib/linux/libclang_rt.builtins-mipsel.so b/clang/test/Driver/Inputs/mips_mti_linux/lib/clang/3.8.0/mipsel-r2-hard-musl/lib/linux/libclang_rt.builtins-mipsel.so new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/clang/test/Driver/Inputs/mips_mti_linux/sysroot/mips-r2-hard-musl/usr/lib/crt1.o b/clang/test/Driver/Inputs/mips_mti_linux/sysroot/mips-r2-hard-musl/usr/lib/crt1.o new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/clang/test/Driver/Inputs/mips_mti_linux/sysroot/mips-r2-hard-musl/usr/lib/crti.o b/clang/test/Driver/Inputs/mips_mti_linux/sysroot/mips-r2-hard-musl/usr/lib/crti.o new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/clang/test/Driver/Inputs/mips_mti_linux/sysroot/mips-r2-hard-musl/usr/lib/crtn.o b/clang/test/Driver/Inputs/mips_mti_linux/sysroot/mips-r2-hard-musl/usr/lib/crtn.o new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/clang/test/Driver/Inputs/mips_mti_linux/sysroot/mipsel-r2-hard-musl/usr/lib/crt1.o b/clang/test/Driver/Inputs/mips_mti_linux/sysroot/mipsel-r2-hard-musl/usr/lib/crt1.o new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/clang/test/Driver/Inputs/mips_mti_linux/sysroot/mipsel-r2-hard-musl/usr/lib/crti.o b/clang/test/Driver/Inputs/mips_mti_linux/sysroot/mipsel-r2-hard-musl/usr/lib/crti.o new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/clang/test/Driver/Inputs/mips_mti_linux/sysroot/mipsel-r2-hard-musl/usr/lib/crtn.o b/clang/test/Driver/Inputs/mips_mti_linux/sysroot/mipsel-r2-hard-musl/usr/lib/crtn.o new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/clang/test/Driver/mips-mti-linux.c b/clang/test/Driver/mips-mti-linux.c new file mode 100644 index 000000000000..c973ed28220a --- /dev/null +++ b/clang/test/Driver/mips-mti-linux.c @@ -0,0 +1,45 @@ +// Check frontend and linker invocations on GPL-free MIPS toolchain. +// +// FIXME: Using --sysroot with this toolchain/triple isn't supported. We use +// it here to test that we are producing the correct paths/flags. +// Ideally, we'd like to have an --llvm-toolchain option similar to +// the --gcc-toolchain one. + +// RUN: false +// XFAIL: * + +// = Big-endian, mips32r2, hard float +// R!N: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// R!N: --target=mips-mti-linux -mips32r2 -mhard-float \ +// R!N: --sysroot=%S/Inputs/mips_mti_linux/sysroot \ +// R!N: | FileCheck --check-prefix=CHECK-BE-HF-32R2 %s +// +// CHECK-BE-HF-32R2: "{{[^"]*}}clang{{[^"]*}}" {{.*}} "-triple" "mips-mti-linux" +// CHECK-BE-HF-32R2-SAME: "-fuse-init-array" "-target-cpu" "mips32r2" +// CHECK-BE-HF-32R2-SAME: "-isysroot" "{{.*}}mips_mti_linux/sysroot" +// CHECK-BE-HF-32R2: "{{[^"]*}}lld{{[^"]*}}" "-flavor" "gnu" "-target" "mips-mti-linux" +// CHECK-BE-HF-32R2-SAME: "--sysroot=[[SYSROOT:[^"]+]]" {{.*}} "-dynamic-linker" "/lib/ld-musl-mips.so.1" +// CHECK-BE-HF-32R2-SAME: "[[SYSROOT]]/mips-r2-hard-musl/usr/lib{{/|\\\\}}crt1.o" +// CHECK-BE-HF-32R2-SAME: "[[SYSROOT]]/mips-r2-hard-musl/usr/lib{{/|\\\\}}crti.o" +// CHECK-BE-HF-32R2-SAME: "-L[[SYSROOT]]/mips-r2-hard-musl/usr/lib" +// CHECK-BE-HF-32R2-SAME: "{{[^"]+}}/mips-r2-hard-musl/lib/linux/libclang_rt.builtins-mips.a" +// CHECK-BE-HF-32R2-SAME: "-lc" +// CHECK-BE-HF-32R2-SAME: "[[SYSROOT]]/mips-r2-hard-musl/usr/lib{{/|\\\\}}crtn.o" + +// = Little-endian, mips32r2, hard float +// R!N: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// R!N: --target=mips-mti-linux -mips32r2 -EL -mhard-float \ +// R!N: --sysroot=%S/Inputs/mips_mti_linux/sysroot \ +// R!N: | FileCheck --check-prefix=CHECK-LE-HF-32R2 %s +// +// CHECK-LE-HF-32R2: "{{[^"]*}}clang{{[^"]*}}" {{.*}} "-triple" "mipsel-mti-linux" +// CHECK-LE-HF-32R2-SAME: "-fuse-init-array" "-target-cpu" "mips32r2" +// CHECK-LE-HF-32R2-SAME: "-isysroot" "{{.*}}mips_mti_linux/sysroot" +// CHECK-LE-HF-32R2: "{{[^"]*}}lld{{[^"]*}}" "-flavor" "gnu" "-target" "mipsel-mti-linux" +// CHECK-LE-HF-32R2-SAME: "--sysroot=[[SYSROOT:[^"]+]]" {{.*}} "-dynamic-linker" "/lib/ld-musl-mipsel.so.1" +// CHECK-LE-HF-32R2-SAME: "[[SYSROOT]]/mipsel-r2-hard-musl/usr/lib{{/|\\\\}}crt1.o" +// CHECK-LE-HF-32R2-SAME: "[[SYSROOT]]/mipsel-r2-hard-musl/usr/lib{{/|\\\\}}crti.o" +// CHECK-LE-HF-32R2-SAME: "-L[[SYSROOT]]/mipsel-r2-hard-musl/usr/lib" +// CHECK-LE-HF-32R2-SAME: "{{[^"]+}}/mipsel-r2-hard-musl/lib/linux/libclang_rt.builtins-mipsel.a" +// CHECK-LE-HF-32R2-SAME: "-lc" +// CHECK-LE-HF-32R2-SAME: "[[SYSROOT]]/mipsel-r2-hard-musl/usr/lib{{/|\\\\}}crtn.o"