diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Driver/ToolChains/MinGW.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Driver/ToolChains/MinGW.cpp | 401 |
1 files changed, 328 insertions, 73 deletions
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/MinGW.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/MinGW.cpp index 7ba729f36bd8..c81a7ed17029 100644 --- a/contrib/llvm-project/clang/lib/Driver/ToolChains/MinGW.cpp +++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/MinGW.cpp @@ -86,7 +86,9 @@ void tools::MinGW::Linker::AddLibGCC(const ArgList &Args, CmdArgs.push_back("-lmoldname"); CmdArgs.push_back("-lmingwex"); for (auto Lib : Args.getAllArgValues(options::OPT_l)) - if (StringRef(Lib).startswith("msvcr") || StringRef(Lib).startswith("ucrt")) + if (StringRef(Lib).starts_with("msvcr") || + StringRef(Lib).starts_with("ucrt") || + StringRef(Lib).starts_with("crtdll")) return; CmdArgs.push_back("-lmsvcrt"); } @@ -98,7 +100,7 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, const char *LinkingOutput) const { const ToolChain &TC = getToolChain(); const Driver &D = TC.getDriver(); - const SanitizerArgs &Sanitize = TC.getSanitizerArgs(); + const SanitizerArgs &Sanitize = TC.getSanitizerArgs(Args); ArgStringList CmdArgs; @@ -130,10 +132,13 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("thumb2pe"); break; case llvm::Triple::aarch64: - CmdArgs.push_back("arm64pe"); + if (TC.getEffectiveTriple().isWindowsArm64EC()) + CmdArgs.push_back("arm64ecpe"); + else + CmdArgs.push_back("arm64pe"); break; default: - llvm_unreachable("Unsupported target architecture."); + D.Diag(diag::err_target_unknown_triple) << TC.getEffectiveTriple().str(); } Arg *SubsysArg = @@ -164,6 +169,24 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("--enable-auto-image-base"); } + if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) + CmdArgs.push_back("--no-demangle"); + + if (!Args.hasFlag(options::OPT_fauto_import, options::OPT_fno_auto_import, + true)) + CmdArgs.push_back("--disable-auto-import"); + + if (Arg *A = Args.getLastArg(options::OPT_mguard_EQ)) { + StringRef GuardArgs = A->getValue(); + if (GuardArgs == "none") + CmdArgs.push_back("--no-guard-cf"); + else if (GuardArgs == "cf" || GuardArgs == "cf-nochecks") + CmdArgs.push_back("--guard-cf"); + else + D.Diag(diag::err_drv_unsupported_option_argument) + << A->getSpelling() << GuardArgs; + } + CmdArgs.push_back("-o"); const char *OutputFile = Output.getFilename(); // GCC implicitly adds an .exe extension if it is given an output file name @@ -176,13 +199,21 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, } else CmdArgs.push_back(OutputFile); - Args.AddAllArgs(CmdArgs, options::OPT_e); // FIXME: add -N, -n flags Args.AddLastArg(CmdArgs, options::OPT_r); Args.AddLastArg(CmdArgs, options::OPT_s); Args.AddLastArg(CmdArgs, options::OPT_t); Args.AddAllArgs(CmdArgs, options::OPT_u_Group); - Args.AddLastArg(CmdArgs, options::OPT_Z_Flag); + + // Add asan_dynamic as the first import lib before other libs. This allows + // asan to be initialized as early as possible to increase its instrumentation + // coverage to include other user DLLs which has not been built with asan. + if (Sanitize.needsAsanRt() && !Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nodefaultlibs)) { + // MinGW always links against a shared MSVCRT. + CmdArgs.push_back( + TC.getCompilerRTArgString(Args, "asan_dynamic", ToolChain::FT_Shared)); + } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_mdll)) { @@ -213,6 +244,17 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); + if (D.isUsingLTO()) { + assert(!Inputs.empty() && "Must have at least one input."); + addLTOOptions(TC, Args, CmdArgs, Output, Inputs[0], + D.getLTOMode() == LTOK_Thin); + } + + if (C.getDriver().IsFlangMode()) { + addFortranRuntimeLibraryPath(TC, Args, CmdArgs); + addFortranRuntimeLibs(TC, Args, CmdArgs); + } + // TODO: Add profile stuff here if (TC.ShouldLinkCXXStdlib(Args)) { @@ -327,10 +369,20 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, Exec, CmdArgs, Inputs, Output)); } +static bool isCrossCompiling(const llvm::Triple &T, bool RequireArchMatch) { + llvm::Triple HostTriple(llvm::Triple::normalize(LLVM_HOST_TRIPLE)); + if (HostTriple.getOS() != llvm::Triple::Win32) + return true; + if (RequireArchMatch && HostTriple.getArch() != T.getArch()) + return true; + return false; +} + // Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple. static bool findGccVersion(StringRef LibDir, std::string &GccLibDir, - std::string &Ver) { - auto Version = toolchains::Generic_GCC::GCCVersion::Parse("0.0.0"); + std::string &Ver, + toolchains::Generic_GCC::GCCVersion &Version) { + Version = toolchains::Generic_GCC::GCCVersion::Parse("0.0.0"); std::error_code EC; for (llvm::sys::fs::directory_iterator LI(LibDir, EC), LE; !EC && LI != LE; LI = LI.increment(EC)) { @@ -348,31 +400,51 @@ static bool findGccVersion(StringRef LibDir, std::string &GccLibDir, return Ver.size(); } -void toolchains::MinGW::findGccLibDir() { - llvm::SmallVector<llvm::SmallString<32>, 2> Archs; - Archs.emplace_back(getTriple().getArchName()); - Archs[0] += "-w64-mingw32"; - Archs.emplace_back("mingw32"); - if (Arch.empty()) - Arch = std::string(Archs[0].str()); +static llvm::Triple getLiteralTriple(const Driver &D, const llvm::Triple &T) { + llvm::Triple LiteralTriple(D.getTargetTriple()); + // The arch portion of the triple may be overridden by -m32/-m64. + LiteralTriple.setArchName(T.getArchName()); + return LiteralTriple; +} + +void toolchains::MinGW::findGccLibDir(const llvm::Triple &LiteralTriple) { + llvm::SmallVector<llvm::SmallString<32>, 5> SubdirNames; + SubdirNames.emplace_back(LiteralTriple.str()); + SubdirNames.emplace_back(getTriple().str()); + SubdirNames.emplace_back(getTriple().getArchName()); + SubdirNames.back() += "-w64-mingw32"; + SubdirNames.emplace_back(getTriple().getArchName()); + SubdirNames.back() += "-w64-mingw32ucrt"; + SubdirNames.emplace_back("mingw32"); + if (SubdirName.empty()) { + SubdirName = getTriple().getArchName(); + SubdirName += "-w64-mingw32"; + } // lib: Arch Linux, Ubuntu, Windows // lib64: openSUSE Linux for (StringRef CandidateLib : {"lib", "lib64"}) { - for (StringRef CandidateArch : Archs) { + for (StringRef CandidateSysroot : SubdirNames) { llvm::SmallString<1024> LibDir(Base); - llvm::sys::path::append(LibDir, CandidateLib, "gcc", CandidateArch); - if (findGccVersion(LibDir, GccLibDir, Ver)) { - Arch = std::string(CandidateArch); + llvm::sys::path::append(LibDir, CandidateLib, "gcc", CandidateSysroot); + if (findGccVersion(LibDir, GccLibDir, Ver, GccVer)) { + SubdirName = std::string(CandidateSysroot); return; } } } } -llvm::ErrorOr<std::string> toolchains::MinGW::findGcc() { - llvm::SmallVector<llvm::SmallString<32>, 2> Gccs; - Gccs.emplace_back(getTriple().getArchName()); - Gccs[0] += "-w64-mingw32-gcc"; +static llvm::ErrorOr<std::string> findGcc(const llvm::Triple &LiteralTriple, + const llvm::Triple &T) { + llvm::SmallVector<llvm::SmallString<32>, 5> Gccs; + Gccs.emplace_back(LiteralTriple.str()); + Gccs.back() += "-gcc"; + Gccs.emplace_back(T.str()); + Gccs.back() += "-gcc"; + Gccs.emplace_back(T.getArchName()); + Gccs.back() += "-w64-mingw32-gcc"; + Gccs.emplace_back(T.getArchName()); + Gccs.back() += "-w64-mingw32ucrt-gcc"; Gccs.emplace_back("mingw32-gcc"); // Please do not add "gcc" here for (StringRef CandidateGcc : Gccs) @@ -381,60 +453,98 @@ llvm::ErrorOr<std::string> toolchains::MinGW::findGcc() { return make_error_code(std::errc::no_such_file_or_directory); } -llvm::ErrorOr<std::string> toolchains::MinGW::findClangRelativeSysroot() { - llvm::SmallVector<llvm::SmallString<32>, 2> Subdirs; - Subdirs.emplace_back(getTriple().str()); - Subdirs.emplace_back(getTriple().getArchName()); - Subdirs[1] += "-w64-mingw32"; - StringRef ClangRoot = - llvm::sys::path::parent_path(getDriver().getInstalledDir()); +static llvm::ErrorOr<std::string> +findClangRelativeSysroot(const Driver &D, const llvm::Triple &LiteralTriple, + const llvm::Triple &T, std::string &SubdirName) { + llvm::SmallVector<llvm::SmallString<32>, 4> Subdirs; + Subdirs.emplace_back(LiteralTriple.str()); + Subdirs.emplace_back(T.str()); + Subdirs.emplace_back(T.getArchName()); + Subdirs.back() += "-w64-mingw32"; + Subdirs.emplace_back(T.getArchName()); + Subdirs.back() += "-w64-mingw32ucrt"; + StringRef ClangRoot = llvm::sys::path::parent_path(D.Dir); StringRef Sep = llvm::sys::path::get_separator(); for (StringRef CandidateSubdir : Subdirs) { if (llvm::sys::fs::is_directory(ClangRoot + Sep + CandidateSubdir)) { - Arch = std::string(CandidateSubdir); + SubdirName = std::string(CandidateSubdir); return (ClangRoot + Sep + CandidateSubdir).str(); } } return make_error_code(std::errc::no_such_file_or_directory); } +static bool looksLikeMinGWSysroot(const std::string &Directory) { + StringRef Sep = llvm::sys::path::get_separator(); + if (!llvm::sys::fs::exists(Directory + Sep + "include" + Sep + "_mingw.h")) + return false; + if (!llvm::sys::fs::exists(Directory + Sep + "lib" + Sep + "libkernel32.a")) + return false; + return true; +} + toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) { - getProgramPaths().push_back(getDriver().getInstalledDir()); + getProgramPaths().push_back(getDriver().Dir); + std::string InstallBase = + std::string(llvm::sys::path::parent_path(getDriver().Dir)); + // The sequence for detecting a sysroot here should be kept in sync with + // the testTriple function below. + llvm::Triple LiteralTriple = getLiteralTriple(D, getTriple()); if (getDriver().SysRoot.size()) Base = getDriver().SysRoot; // Look for <clang-bin>/../<triplet>; if found, use <clang-bin>/.. as the // base as it could still be a base for a gcc setup with libgcc. - else if (llvm::ErrorOr<std::string> TargetSubdir = findClangRelativeSysroot()) + else if (llvm::ErrorOr<std::string> TargetSubdir = findClangRelativeSysroot( + getDriver(), LiteralTriple, getTriple(), SubdirName)) Base = std::string(llvm::sys::path::parent_path(TargetSubdir.get())); - else if (llvm::ErrorOr<std::string> GPPName = findGcc()) + // If the install base of Clang seems to have mingw sysroot files directly + // in the toplevel include and lib directories, use this as base instead of + // looking for a triple prefixed GCC in the path. + else if (looksLikeMinGWSysroot(InstallBase)) + Base = InstallBase; + else if (llvm::ErrorOr<std::string> GPPName = + findGcc(LiteralTriple, getTriple())) Base = std::string(llvm::sys::path::parent_path( llvm::sys::path::parent_path(GPPName.get()))); else - Base = std::string( - llvm::sys::path::parent_path(getDriver().getInstalledDir())); + Base = InstallBase; Base += llvm::sys::path::get_separator(); - findGccLibDir(); + findGccLibDir(LiteralTriple); + TripleDirName = SubdirName; // GccLibDir must precede Base/lib so that the // correct crtbegin.o ,cetend.o would be found. getFilePaths().push_back(GccLibDir); + + // openSUSE/Fedora + std::string CandidateSubdir = SubdirName + "/sys-root/mingw"; + if (getDriver().getVFS().exists(Base + CandidateSubdir)) + SubdirName = CandidateSubdir; + getFilePaths().push_back( - (Base + Arch + llvm::sys::path::get_separator() + "lib").str()); - getFilePaths().push_back(Base + "lib"); - // openSUSE - getFilePaths().push_back(Base + Arch + "/sys-root/mingw/lib"); + (Base + SubdirName + llvm::sys::path::get_separator() + "lib").str()); + + // Gentoo + getFilePaths().push_back( + (Base + SubdirName + llvm::sys::path::get_separator() + "mingw/lib").str()); + + // Only include <base>/lib if we're not cross compiling (not even for + // windows->windows to a different arch), or if the sysroot has been set + // (where we presume the user has pointed it at an arch specific + // subdirectory). + if (!::isCrossCompiling(getTriple(), /*RequireArchMatch=*/true) || + getDriver().SysRoot.size()) + getFilePaths().push_back(Base + "lib"); NativeLLVMSupport = Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER) .equals_insensitive("lld"); } -bool toolchains::MinGW::IsIntegratedAssemblerDefault() const { return true; } - Tool *toolchains::MinGW::getTool(Action::ActionClass AC) const { switch (AC) { case Action::PreprocessJobClass: @@ -462,30 +572,36 @@ bool toolchains::MinGW::HasNativeLLVMSupport() const { return NativeLLVMSupport; } -bool toolchains::MinGW::IsUnwindTablesDefault(const ArgList &Args) const { +ToolChain::UnwindTableLevel +toolchains::MinGW::getDefaultUnwindTableLevel(const ArgList &Args) const { Arg *ExceptionArg = Args.getLastArg(options::OPT_fsjlj_exceptions, options::OPT_fseh_exceptions, options::OPT_fdwarf_exceptions); if (ExceptionArg && ExceptionArg->getOption().matches(options::OPT_fseh_exceptions)) - return true; - return getArch() == llvm::Triple::x86_64 || - getArch() == llvm::Triple::aarch64; + return UnwindTableLevel::Asynchronous; + + if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::arm || + getArch() == llvm::Triple::thumb || getArch() == llvm::Triple::aarch64) + return UnwindTableLevel::Asynchronous; + return UnwindTableLevel::None; } bool toolchains::MinGW::isPICDefault() const { - return getArch() == llvm::Triple::x86_64; + return getArch() == llvm::Triple::x86_64 || + getArch() == llvm::Triple::aarch64; } -bool toolchains::MinGW::isPIEDefault() const { return false; } - -bool toolchains::MinGW::isPICDefaultForced() const { - return getArch() == llvm::Triple::x86_64; +bool toolchains::MinGW::isPIEDefault(const llvm::opt::ArgList &Args) const { + return false; } +bool toolchains::MinGW::isPICDefaultForced() const { return true; } + llvm::ExceptionHandling toolchains::MinGW::GetExceptionModel(const ArgList &Args) const { - if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::aarch64) + if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::aarch64 || + getArch() == llvm::Triple::arm || getArch() == llvm::Triple::thumb) return llvm::ExceptionHandling::WinEH; return llvm::ExceptionHandling::DwarfCFI; } @@ -501,17 +617,17 @@ SanitizerMask toolchains::MinGW::getSupportedSanitizers() const { void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { - CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args); + CudaInstallation->AddCudaIncludeArgs(DriverArgs, CC1Args); } void toolchains::MinGW::AddHIPIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { - RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args); + RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args); } void toolchains::MinGW::printVerboseInfo(raw_ostream &OS) const { - CudaInstallation.print(OS); - RocmInstallation.print(OS); + CudaInstallation->print(OS); + RocmInstallation->print(OS); } // Include directories for various hosts: @@ -554,6 +670,12 @@ void toolchains::MinGW::printVerboseInfo(raw_ostream &OS) const { // /usr/include/c++/4.8/backward // /usr/x86_64-w64-mingw32/include +// Fedora +// /usr/x86_64-w64-mingw32ucrt/sys-root/mingw/include/c++/x86_64-w64-mingw32ucrt +// /usr/x86_64-w64-mingw32ucrt/sys-root/mingw/include/c++/backward +// /usr/x86_64-w64-mingw32ucrt/sys-root/mingw/include +// /usr/lib/gcc/x86_64-w64-mingw32ucrt/12.2.1/include-fixed + void toolchains::MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { if (DriverArgs.hasArg(options::OPT_nostdinc)) @@ -568,49 +690,182 @@ void toolchains::MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs, if (DriverArgs.hasArg(options::OPT_nostdlibinc)) return; - if (GetRuntimeLibType(DriverArgs) == ToolChain::RLT_Libgcc) { - // openSUSE - addSystemInclude(DriverArgs, CC1Args, - Base + Arch + "/sys-root/mingw/include"); - } + addSystemInclude(DriverArgs, CC1Args, + Base + SubdirName + llvm::sys::path::get_separator() + + "include"); + // Gentoo addSystemInclude(DriverArgs, CC1Args, - Base + Arch + llvm::sys::path::get_separator() + "include"); - addSystemInclude(DriverArgs, CC1Args, Base + "include"); + Base + SubdirName + llvm::sys::path::get_separator() + "usr/include"); + + // Only include <base>/include if we're not cross compiling (but do allow it + // if we're on Windows and building for Windows on another architecture), + // or if the sysroot has been set (where we presume the user has pointed it + // at an arch specific subdirectory). + if (!::isCrossCompiling(getTriple(), /*RequireArchMatch=*/false) || + getDriver().SysRoot.size()) + addSystemInclude(DriverArgs, CC1Args, Base + "include"); +} + +void toolchains::MinGW::addClangTargetOptions( + const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, + Action::OffloadKind DeviceOffloadKind) const { + if (Arg *A = DriverArgs.getLastArg(options::OPT_mguard_EQ)) { + StringRef GuardArgs = A->getValue(); + if (GuardArgs == "none") { + // Do nothing. + } else if (GuardArgs == "cf") { + // Emit CFG instrumentation and the table of address-taken functions. + CC1Args.push_back("-cfguard"); + } else if (GuardArgs == "cf-nochecks") { + // Emit only the table of address-taken functions. + CC1Args.push_back("-cfguard-no-checks"); + } else { + getDriver().Diag(diag::err_drv_unsupported_option_argument) + << A->getSpelling() << GuardArgs; + } + } + + // Default to not enabling sized deallocation, but let user provided options + // override it. + // + // If using sized deallocation, user code that invokes delete will end up + // calling delete(void*,size_t). If the user wanted to override the + // operator delete(void*), there may be a fallback operator + // delete(void*,size_t) which calls the regular operator delete(void*). + // + // However, if the C++ standard library is linked in the form of a DLL, + // and the fallback operator delete(void*,size_t) is within this DLL (which is + // the case for libc++ at least) it will only redirect towards the library's + // default operator delete(void*), not towards the user's provided operator + // delete(void*). + // + // This issue can be avoided, if the fallback operators are linked statically + // into the callers, even if the C++ standard library is linked as a DLL. + // + // This is meant as a temporary workaround until libc++ implements this + // technique, which is tracked in + // https://github.com/llvm/llvm-project/issues/96899. + if (!DriverArgs.hasArgNoClaim(options::OPT_fsized_deallocation, + options::OPT_fno_sized_deallocation)) + CC1Args.push_back("-fno-sized-deallocation"); + + CC1Args.push_back("-fno-use-init-array"); + + for (auto Opt : {options::OPT_mthreads, options::OPT_mwindows, + options::OPT_mconsole, options::OPT_mdll}) { + if (Arg *A = DriverArgs.getLastArgNoClaim(Opt)) + A->ignoreTargetSpecific(); + } } void toolchains::MinGW::AddClangCXXStdlibIncludeArgs( const ArgList &DriverArgs, ArgStringList &CC1Args) const { - if (DriverArgs.hasArg(options::OPT_nostdlibinc) || - DriverArgs.hasArg(options::OPT_nostdincxx)) + if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc, + options::OPT_nostdincxx)) return; StringRef Slash = llvm::sys::path::get_separator(); switch (GetCXXStdlibType(DriverArgs)) { - case ToolChain::CST_Libcxx: - addSystemInclude(DriverArgs, CC1Args, Base + Arch + Slash + "include" + - Slash + "c++" + Slash + "v1"); + case ToolChain::CST_Libcxx: { + std::string TargetDir = (Base + "include" + Slash + getTripleString() + + Slash + "c++" + Slash + "v1") + .str(); + if (getDriver().getVFS().exists(TargetDir)) + addSystemInclude(DriverArgs, CC1Args, TargetDir); + addSystemInclude(DriverArgs, CC1Args, + Base + SubdirName + Slash + "include" + Slash + "c++" + + Slash + "v1"); addSystemInclude(DriverArgs, CC1Args, Base + "include" + Slash + "c++" + Slash + "v1"); break; + } case ToolChain::CST_Libstdcxx: - llvm::SmallVector<llvm::SmallString<1024>, 4> CppIncludeBases; + llvm::SmallVector<llvm::SmallString<1024>, 7> CppIncludeBases; CppIncludeBases.emplace_back(Base); - llvm::sys::path::append(CppIncludeBases[0], Arch, "include", "c++"); + llvm::sys::path::append(CppIncludeBases[0], SubdirName, "include", "c++"); CppIncludeBases.emplace_back(Base); - llvm::sys::path::append(CppIncludeBases[1], Arch, "include", "c++", Ver); + llvm::sys::path::append(CppIncludeBases[1], SubdirName, "include", "c++", + Ver); CppIncludeBases.emplace_back(Base); llvm::sys::path::append(CppIncludeBases[2], "include", "c++", Ver); CppIncludeBases.emplace_back(GccLibDir); llvm::sys::path::append(CppIncludeBases[3], "include", "c++"); + CppIncludeBases.emplace_back(GccLibDir); + llvm::sys::path::append(CppIncludeBases[4], "include", + "g++-v" + GccVer.Text); + CppIncludeBases.emplace_back(GccLibDir); + llvm::sys::path::append(CppIncludeBases[5], "include", + "g++-v" + GccVer.MajorStr + "." + GccVer.MinorStr); + CppIncludeBases.emplace_back(GccLibDir); + llvm::sys::path::append(CppIncludeBases[6], "include", + "g++-v" + GccVer.MajorStr); for (auto &CppIncludeBase : CppIncludeBases) { addSystemInclude(DriverArgs, CC1Args, CppIncludeBase); CppIncludeBase += Slash; - addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + Arch); + addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + TripleDirName); addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + "backward"); } break; } } + +static bool testTriple(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) { + // If an explicit sysroot is set, that will be used and we shouldn't try to + // detect anything else. + std::string SubdirName; + if (D.SysRoot.size()) + return true; + llvm::Triple LiteralTriple = getLiteralTriple(D, Triple); + std::string InstallBase = std::string(llvm::sys::path::parent_path(D.Dir)); + if (llvm::ErrorOr<std::string> TargetSubdir = + findClangRelativeSysroot(D, LiteralTriple, Triple, SubdirName)) + return true; + // If the install base itself looks like a mingw sysroot, we'll use that + // - don't use any potentially unrelated gcc to influence what triple to use. + if (looksLikeMinGWSysroot(InstallBase)) + return false; + if (llvm::ErrorOr<std::string> GPPName = findGcc(LiteralTriple, Triple)) + return true; + // If we neither found a colocated sysroot or a matching gcc executable, + // conclude that we can't know if this is the correct spelling of the triple. + return false; +} + +static llvm::Triple adjustTriple(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) { + // First test if the original triple can find a sysroot with the triple + // name. + if (testTriple(D, Triple, Args)) + return Triple; + llvm::SmallVector<llvm::StringRef, 3> Archs; + // If not, test a couple other possible arch names that might be what was + // intended. + if (Triple.getArch() == llvm::Triple::x86) { + Archs.emplace_back("i386"); + Archs.emplace_back("i586"); + Archs.emplace_back("i686"); + } else if (Triple.getArch() == llvm::Triple::arm || + Triple.getArch() == llvm::Triple::thumb) { + Archs.emplace_back("armv7"); + } + for (auto A : Archs) { + llvm::Triple TestTriple(Triple); + TestTriple.setArchName(A); + if (testTriple(D, TestTriple, Args)) + return TestTriple; + } + // If none was found, just proceed with the original value. + return Triple; +} + +void toolchains::MinGW::fixTripleArch(const Driver &D, llvm::Triple &Triple, + const ArgList &Args) { + if (Triple.getArch() == llvm::Triple::x86 || + Triple.getArch() == llvm::Triple::arm || + Triple.getArch() == llvm::Triple::thumb) + Triple = adjustTriple(D, Triple, Args); +} |