10b57cec5SDimitry Andric //===--- MinGW.cpp - MinGWToolChain Implementation ------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "MinGW.h" 100b57cec5SDimitry Andric #include "InputInfo.h" 110b57cec5SDimitry Andric #include "CommonArgs.h" 120b57cec5SDimitry Andric #include "clang/Config/config.h" 130b57cec5SDimitry Andric #include "clang/Driver/Compilation.h" 140b57cec5SDimitry Andric #include "clang/Driver/Driver.h" 150b57cec5SDimitry Andric #include "clang/Driver/DriverDiagnostic.h" 160b57cec5SDimitry Andric #include "clang/Driver/Options.h" 170b57cec5SDimitry Andric #include "clang/Driver/SanitizerArgs.h" 180b57cec5SDimitry Andric #include "llvm/Option/ArgList.h" 190b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h" 200b57cec5SDimitry Andric #include "llvm/Support/Path.h" 210b57cec5SDimitry Andric #include <system_error> 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric using namespace clang::diag; 240b57cec5SDimitry Andric using namespace clang::driver; 250b57cec5SDimitry Andric using namespace clang; 260b57cec5SDimitry Andric using namespace llvm::opt; 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric /// MinGW Tools 290b57cec5SDimitry Andric void tools::MinGW::Assembler::ConstructJob(Compilation &C, const JobAction &JA, 300b57cec5SDimitry Andric const InputInfo &Output, 310b57cec5SDimitry Andric const InputInfoList &Inputs, 320b57cec5SDimitry Andric const ArgList &Args, 330b57cec5SDimitry Andric const char *LinkingOutput) const { 340b57cec5SDimitry Andric claimNoWarnArgs(Args); 350b57cec5SDimitry Andric ArgStringList CmdArgs; 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric if (getToolChain().getArch() == llvm::Triple::x86) { 380b57cec5SDimitry Andric CmdArgs.push_back("--32"); 390b57cec5SDimitry Andric } else if (getToolChain().getArch() == llvm::Triple::x86_64) { 400b57cec5SDimitry Andric CmdArgs.push_back("--64"); 410b57cec5SDimitry Andric } 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric CmdArgs.push_back("-o"); 460b57cec5SDimitry Andric CmdArgs.push_back(Output.getFilename()); 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric for (const auto &II : Inputs) 490b57cec5SDimitry Andric CmdArgs.push_back(II.getFilename()); 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); 52a7dea167SDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric if (Args.hasArg(options::OPT_gsplit_dwarf)) 550b57cec5SDimitry Andric SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, 560b57cec5SDimitry Andric SplitDebugName(Args, Inputs[0], Output)); 570b57cec5SDimitry Andric } 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric void tools::MinGW::Linker::AddLibGCC(const ArgList &Args, 600b57cec5SDimitry Andric ArgStringList &CmdArgs) const { 610b57cec5SDimitry Andric if (Args.hasArg(options::OPT_mthreads)) 620b57cec5SDimitry Andric CmdArgs.push_back("-lmingwthrd"); 630b57cec5SDimitry Andric CmdArgs.push_back("-lmingw32"); 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric // Make use of compiler-rt if --rtlib option is used 660b57cec5SDimitry Andric ToolChain::RuntimeLibType RLT = getToolChain().GetRuntimeLibType(Args); 670b57cec5SDimitry Andric if (RLT == ToolChain::RLT_Libgcc) { 680b57cec5SDimitry Andric bool Static = Args.hasArg(options::OPT_static_libgcc) || 690b57cec5SDimitry Andric Args.hasArg(options::OPT_static); 700b57cec5SDimitry Andric bool Shared = Args.hasArg(options::OPT_shared); 710b57cec5SDimitry Andric bool CXX = getToolChain().getDriver().CCCIsCXX(); 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric if (Static || (!CXX && !Shared)) { 740b57cec5SDimitry Andric CmdArgs.push_back("-lgcc"); 750b57cec5SDimitry Andric CmdArgs.push_back("-lgcc_eh"); 760b57cec5SDimitry Andric } else { 770b57cec5SDimitry Andric CmdArgs.push_back("-lgcc_s"); 780b57cec5SDimitry Andric CmdArgs.push_back("-lgcc"); 790b57cec5SDimitry Andric } 800b57cec5SDimitry Andric } else { 810b57cec5SDimitry Andric AddRunTimeLibs(getToolChain(), getToolChain().getDriver(), CmdArgs, Args); 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric CmdArgs.push_back("-lmoldname"); 850b57cec5SDimitry Andric CmdArgs.push_back("-lmingwex"); 860b57cec5SDimitry Andric for (auto Lib : Args.getAllArgValues(options::OPT_l)) 870b57cec5SDimitry Andric if (StringRef(Lib).startswith("msvcr") || StringRef(Lib).startswith("ucrt")) 880b57cec5SDimitry Andric return; 890b57cec5SDimitry Andric CmdArgs.push_back("-lmsvcrt"); 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, 930b57cec5SDimitry Andric const InputInfo &Output, 940b57cec5SDimitry Andric const InputInfoList &Inputs, 950b57cec5SDimitry Andric const ArgList &Args, 960b57cec5SDimitry Andric const char *LinkingOutput) const { 970b57cec5SDimitry Andric const ToolChain &TC = getToolChain(); 980b57cec5SDimitry Andric const Driver &D = TC.getDriver(); 990b57cec5SDimitry Andric const SanitizerArgs &Sanitize = TC.getSanitizerArgs(); 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric ArgStringList CmdArgs; 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric // Silence warning for "clang -g foo.o -o foo" 1040b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_g_Group); 1050b57cec5SDimitry Andric // and "clang -emit-llvm foo.o -o foo" 1060b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_emit_llvm); 1070b57cec5SDimitry Andric // and for "clang -w foo.o -o foo". Other warning options are already 1080b57cec5SDimitry Andric // handled somewhere else. 1090b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_w); 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric if (!D.SysRoot.empty()) 1120b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric if (Args.hasArg(options::OPT_s)) 1150b57cec5SDimitry Andric CmdArgs.push_back("-s"); 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric CmdArgs.push_back("-m"); 1180b57cec5SDimitry Andric switch (TC.getArch()) { 1190b57cec5SDimitry Andric case llvm::Triple::x86: 1200b57cec5SDimitry Andric CmdArgs.push_back("i386pe"); 1210b57cec5SDimitry Andric break; 1220b57cec5SDimitry Andric case llvm::Triple::x86_64: 1230b57cec5SDimitry Andric CmdArgs.push_back("i386pep"); 1240b57cec5SDimitry Andric break; 1250b57cec5SDimitry Andric case llvm::Triple::arm: 1260b57cec5SDimitry Andric case llvm::Triple::thumb: 1270b57cec5SDimitry Andric // FIXME: this is incorrect for WinCE 1280b57cec5SDimitry Andric CmdArgs.push_back("thumb2pe"); 1290b57cec5SDimitry Andric break; 1300b57cec5SDimitry Andric case llvm::Triple::aarch64: 1310b57cec5SDimitry Andric CmdArgs.push_back("arm64pe"); 1320b57cec5SDimitry Andric break; 1330b57cec5SDimitry Andric default: 1340b57cec5SDimitry Andric llvm_unreachable("Unsupported target architecture."); 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric if (Args.hasArg(options::OPT_mwindows)) { 1380b57cec5SDimitry Andric CmdArgs.push_back("--subsystem"); 1390b57cec5SDimitry Andric CmdArgs.push_back("windows"); 1400b57cec5SDimitry Andric } else if (Args.hasArg(options::OPT_mconsole)) { 1410b57cec5SDimitry Andric CmdArgs.push_back("--subsystem"); 1420b57cec5SDimitry Andric CmdArgs.push_back("console"); 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric if (Args.hasArg(options::OPT_mdll)) 1460b57cec5SDimitry Andric CmdArgs.push_back("--dll"); 1470b57cec5SDimitry Andric else if (Args.hasArg(options::OPT_shared)) 1480b57cec5SDimitry Andric CmdArgs.push_back("--shared"); 1490b57cec5SDimitry Andric if (Args.hasArg(options::OPT_static)) 1500b57cec5SDimitry Andric CmdArgs.push_back("-Bstatic"); 1510b57cec5SDimitry Andric else 1520b57cec5SDimitry Andric CmdArgs.push_back("-Bdynamic"); 1530b57cec5SDimitry Andric if (Args.hasArg(options::OPT_mdll) || Args.hasArg(options::OPT_shared)) { 1540b57cec5SDimitry Andric CmdArgs.push_back("-e"); 1550b57cec5SDimitry Andric if (TC.getArch() == llvm::Triple::x86) 1560b57cec5SDimitry Andric CmdArgs.push_back("_DllMainCRTStartup@12"); 1570b57cec5SDimitry Andric else 1580b57cec5SDimitry Andric CmdArgs.push_back("DllMainCRTStartup"); 1590b57cec5SDimitry Andric CmdArgs.push_back("--enable-auto-image-base"); 1600b57cec5SDimitry Andric } 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric CmdArgs.push_back("-o"); 163*480093f4SDimitry Andric const char *OutputFile = Output.getFilename(); 164*480093f4SDimitry Andric // GCC implicitly adds an .exe extension if it is given an output file name 165*480093f4SDimitry Andric // that lacks an extension. However, GCC only does this when actually 166*480093f4SDimitry Andric // running on windows, not when operating as a cross compiler. As some users 167*480093f4SDimitry Andric // have come to rely on this behaviour, try to replicate it. 168*480093f4SDimitry Andric #ifdef _WIN32 169*480093f4SDimitry Andric if (!llvm::sys::path::has_extension(OutputFile)) 170*480093f4SDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine(OutputFile) + ".exe")); 171*480093f4SDimitry Andric else 172*480093f4SDimitry Andric CmdArgs.push_back(OutputFile); 173*480093f4SDimitry Andric #else 174*480093f4SDimitry Andric CmdArgs.push_back(OutputFile); 175*480093f4SDimitry Andric #endif 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_e); 1780b57cec5SDimitry Andric // FIXME: add -N, -n flags 1790b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_r); 1800b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_s); 1810b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_t); 1820b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_u_Group); 1830b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_Z_Flag); 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { 1860b57cec5SDimitry Andric if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_mdll)) { 1870b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("dllcrt2.o"))); 1880b57cec5SDimitry Andric } else { 1890b57cec5SDimitry Andric if (Args.hasArg(options::OPT_municode)) 1900b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2u.o"))); 1910b57cec5SDimitry Andric else 1920b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2.o"))); 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric if (Args.hasArg(options::OPT_pg)) 1950b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("gcrt2.o"))); 1960b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o"))); 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_L); 2000b57cec5SDimitry Andric TC.AddFilePathLibArgs(Args, CmdArgs); 2010b57cec5SDimitry Andric AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric // TODO: Add profile stuff here 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric if (TC.ShouldLinkCXXStdlib(Args)) { 2060b57cec5SDimitry Andric bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && 2070b57cec5SDimitry Andric !Args.hasArg(options::OPT_static); 2080b57cec5SDimitry Andric if (OnlyLibstdcxxStatic) 2090b57cec5SDimitry Andric CmdArgs.push_back("-Bstatic"); 2100b57cec5SDimitry Andric TC.AddCXXStdlibLibArgs(Args, CmdArgs); 2110b57cec5SDimitry Andric if (OnlyLibstdcxxStatic) 2120b57cec5SDimitry Andric CmdArgs.push_back("-Bdynamic"); 2130b57cec5SDimitry Andric } 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric bool HasWindowsApp = false; 2160b57cec5SDimitry Andric for (auto Lib : Args.getAllArgValues(options::OPT_l)) { 2170b57cec5SDimitry Andric if (Lib == "windowsapp") { 2180b57cec5SDimitry Andric HasWindowsApp = true; 2190b57cec5SDimitry Andric break; 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib)) { 2240b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nodefaultlibs)) { 2250b57cec5SDimitry Andric if (Args.hasArg(options::OPT_static)) 2260b57cec5SDimitry Andric CmdArgs.push_back("--start-group"); 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric if (Args.hasArg(options::OPT_fstack_protector) || 2290b57cec5SDimitry Andric Args.hasArg(options::OPT_fstack_protector_strong) || 2300b57cec5SDimitry Andric Args.hasArg(options::OPT_fstack_protector_all)) { 2310b57cec5SDimitry Andric CmdArgs.push_back("-lssp_nonshared"); 2320b57cec5SDimitry Andric CmdArgs.push_back("-lssp"); 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, 2360b57cec5SDimitry Andric options::OPT_fno_openmp, false)) { 2370b57cec5SDimitry Andric switch (TC.getDriver().getOpenMPRuntime(Args)) { 2380b57cec5SDimitry Andric case Driver::OMPRT_OMP: 2390b57cec5SDimitry Andric CmdArgs.push_back("-lomp"); 2400b57cec5SDimitry Andric break; 2410b57cec5SDimitry Andric case Driver::OMPRT_IOMP5: 2420b57cec5SDimitry Andric CmdArgs.push_back("-liomp5md"); 2430b57cec5SDimitry Andric break; 2440b57cec5SDimitry Andric case Driver::OMPRT_GOMP: 2450b57cec5SDimitry Andric CmdArgs.push_back("-lgomp"); 2460b57cec5SDimitry Andric break; 2470b57cec5SDimitry Andric case Driver::OMPRT_Unknown: 2480b57cec5SDimitry Andric // Already diagnosed. 2490b57cec5SDimitry Andric break; 2500b57cec5SDimitry Andric } 2510b57cec5SDimitry Andric } 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric AddLibGCC(Args, CmdArgs); 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric if (Args.hasArg(options::OPT_pg)) 2560b57cec5SDimitry Andric CmdArgs.push_back("-lgmon"); 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric if (Args.hasArg(options::OPT_pthread)) 2590b57cec5SDimitry Andric CmdArgs.push_back("-lpthread"); 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric if (Sanitize.needsAsanRt()) { 2620b57cec5SDimitry Andric // MinGW always links against a shared MSVCRT. 2630b57cec5SDimitry Andric CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dynamic", 2640b57cec5SDimitry Andric ToolChain::FT_Shared)); 2650b57cec5SDimitry Andric CmdArgs.push_back( 2660b57cec5SDimitry Andric TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); 2670b57cec5SDimitry Andric CmdArgs.push_back("--require-defined"); 2680b57cec5SDimitry Andric CmdArgs.push_back(TC.getArch() == llvm::Triple::x86 2690b57cec5SDimitry Andric ? "___asan_seh_interceptor" 2700b57cec5SDimitry Andric : "__asan_seh_interceptor"); 2710b57cec5SDimitry Andric // Make sure the linker consider all object files from the dynamic 2720b57cec5SDimitry Andric // runtime thunk. 2730b57cec5SDimitry Andric CmdArgs.push_back("--whole-archive"); 2740b57cec5SDimitry Andric CmdArgs.push_back( 2750b57cec5SDimitry Andric TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); 2760b57cec5SDimitry Andric CmdArgs.push_back("--no-whole-archive"); 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric TC.addProfileRTLibs(Args, CmdArgs); 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric if (!HasWindowsApp) { 2820b57cec5SDimitry Andric // Add system libraries. If linking to libwindowsapp.a, that import 2830b57cec5SDimitry Andric // library replaces all these and we shouldn't accidentally try to 2840b57cec5SDimitry Andric // link to the normal desktop mode dlls. 2850b57cec5SDimitry Andric if (Args.hasArg(options::OPT_mwindows)) { 2860b57cec5SDimitry Andric CmdArgs.push_back("-lgdi32"); 2870b57cec5SDimitry Andric CmdArgs.push_back("-lcomdlg32"); 2880b57cec5SDimitry Andric } 2890b57cec5SDimitry Andric CmdArgs.push_back("-ladvapi32"); 2900b57cec5SDimitry Andric CmdArgs.push_back("-lshell32"); 2910b57cec5SDimitry Andric CmdArgs.push_back("-luser32"); 2920b57cec5SDimitry Andric CmdArgs.push_back("-lkernel32"); 2930b57cec5SDimitry Andric } 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric if (Args.hasArg(options::OPT_static)) 2960b57cec5SDimitry Andric CmdArgs.push_back("--end-group"); 2970b57cec5SDimitry Andric else 2980b57cec5SDimitry Andric AddLibGCC(Args, CmdArgs); 2990b57cec5SDimitry Andric } 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostartfiles)) { 3020b57cec5SDimitry Andric // Add crtfastmath.o if available and fast math is enabled. 3030b57cec5SDimitry Andric TC.AddFastMathRuntimeIfAvailable(Args, CmdArgs); 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o"))); 3060b57cec5SDimitry Andric } 3070b57cec5SDimitry Andric } 3080b57cec5SDimitry Andric const char *Exec = Args.MakeArgString(TC.GetLinkerPath()); 309a7dea167SDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); 3100b57cec5SDimitry Andric } 3110b57cec5SDimitry Andric 3120b57cec5SDimitry Andric // Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple. 3130b57cec5SDimitry Andric static bool findGccVersion(StringRef LibDir, std::string &GccLibDir, 3140b57cec5SDimitry Andric std::string &Ver) { 3150b57cec5SDimitry Andric auto Version = toolchains::Generic_GCC::GCCVersion::Parse("0.0.0"); 3160b57cec5SDimitry Andric std::error_code EC; 3170b57cec5SDimitry Andric for (llvm::sys::fs::directory_iterator LI(LibDir, EC), LE; !EC && LI != LE; 3180b57cec5SDimitry Andric LI = LI.increment(EC)) { 3190b57cec5SDimitry Andric StringRef VersionText = llvm::sys::path::filename(LI->path()); 3200b57cec5SDimitry Andric auto CandidateVersion = 3210b57cec5SDimitry Andric toolchains::Generic_GCC::GCCVersion::Parse(VersionText); 3220b57cec5SDimitry Andric if (CandidateVersion.Major == -1) 3230b57cec5SDimitry Andric continue; 3240b57cec5SDimitry Andric if (CandidateVersion <= Version) 3250b57cec5SDimitry Andric continue; 3260b57cec5SDimitry Andric Ver = VersionText; 3270b57cec5SDimitry Andric GccLibDir = LI->path(); 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric return Ver.size(); 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric void toolchains::MinGW::findGccLibDir() { 3330b57cec5SDimitry Andric llvm::SmallVector<llvm::SmallString<32>, 2> Archs; 3340b57cec5SDimitry Andric Archs.emplace_back(getTriple().getArchName()); 3350b57cec5SDimitry Andric Archs[0] += "-w64-mingw32"; 3360b57cec5SDimitry Andric Archs.emplace_back("mingw32"); 3370b57cec5SDimitry Andric if (Arch.empty()) 3380b57cec5SDimitry Andric Arch = Archs[0].str(); 3390b57cec5SDimitry Andric // lib: Arch Linux, Ubuntu, Windows 3400b57cec5SDimitry Andric // lib64: openSUSE Linux 3410b57cec5SDimitry Andric for (StringRef CandidateLib : {"lib", "lib64"}) { 3420b57cec5SDimitry Andric for (StringRef CandidateArch : Archs) { 3430b57cec5SDimitry Andric llvm::SmallString<1024> LibDir(Base); 3440b57cec5SDimitry Andric llvm::sys::path::append(LibDir, CandidateLib, "gcc", CandidateArch); 3450b57cec5SDimitry Andric if (findGccVersion(LibDir, GccLibDir, Ver)) { 3460b57cec5SDimitry Andric Arch = CandidateArch; 3470b57cec5SDimitry Andric return; 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric } 3500b57cec5SDimitry Andric } 3510b57cec5SDimitry Andric } 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric llvm::ErrorOr<std::string> toolchains::MinGW::findGcc() { 3540b57cec5SDimitry Andric llvm::SmallVector<llvm::SmallString<32>, 2> Gccs; 3550b57cec5SDimitry Andric Gccs.emplace_back(getTriple().getArchName()); 3560b57cec5SDimitry Andric Gccs[0] += "-w64-mingw32-gcc"; 3570b57cec5SDimitry Andric Gccs.emplace_back("mingw32-gcc"); 3580b57cec5SDimitry Andric // Please do not add "gcc" here 3590b57cec5SDimitry Andric for (StringRef CandidateGcc : Gccs) 3600b57cec5SDimitry Andric if (llvm::ErrorOr<std::string> GPPName = llvm::sys::findProgramByName(CandidateGcc)) 3610b57cec5SDimitry Andric return GPPName; 3620b57cec5SDimitry Andric return make_error_code(std::errc::no_such_file_or_directory); 3630b57cec5SDimitry Andric } 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric llvm::ErrorOr<std::string> toolchains::MinGW::findClangRelativeSysroot() { 3660b57cec5SDimitry Andric llvm::SmallVector<llvm::SmallString<32>, 2> Subdirs; 3670b57cec5SDimitry Andric Subdirs.emplace_back(getTriple().str()); 3680b57cec5SDimitry Andric Subdirs.emplace_back(getTriple().getArchName()); 3690b57cec5SDimitry Andric Subdirs[1] += "-w64-mingw32"; 3700b57cec5SDimitry Andric StringRef ClangRoot = 3710b57cec5SDimitry Andric llvm::sys::path::parent_path(getDriver().getInstalledDir()); 3720b57cec5SDimitry Andric StringRef Sep = llvm::sys::path::get_separator(); 3730b57cec5SDimitry Andric for (StringRef CandidateSubdir : Subdirs) { 3740b57cec5SDimitry Andric if (llvm::sys::fs::is_directory(ClangRoot + Sep + CandidateSubdir)) { 3750b57cec5SDimitry Andric Arch = CandidateSubdir; 3760b57cec5SDimitry Andric return (ClangRoot + Sep + CandidateSubdir).str(); 3770b57cec5SDimitry Andric } 3780b57cec5SDimitry Andric } 3790b57cec5SDimitry Andric return make_error_code(std::errc::no_such_file_or_directory); 3800b57cec5SDimitry Andric } 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, 3830b57cec5SDimitry Andric const ArgList &Args) 3840b57cec5SDimitry Andric : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args) { 3850b57cec5SDimitry Andric getProgramPaths().push_back(getDriver().getInstalledDir()); 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric if (getDriver().SysRoot.size()) 3880b57cec5SDimitry Andric Base = getDriver().SysRoot; 3890b57cec5SDimitry Andric // Look for <clang-bin>/../<triplet>; if found, use <clang-bin>/.. as the 3900b57cec5SDimitry Andric // base as it could still be a base for a gcc setup with libgcc. 3910b57cec5SDimitry Andric else if (llvm::ErrorOr<std::string> TargetSubdir = findClangRelativeSysroot()) 3920b57cec5SDimitry Andric Base = llvm::sys::path::parent_path(TargetSubdir.get()); 3930b57cec5SDimitry Andric else if (llvm::ErrorOr<std::string> GPPName = findGcc()) 3940b57cec5SDimitry Andric Base = llvm::sys::path::parent_path( 3950b57cec5SDimitry Andric llvm::sys::path::parent_path(GPPName.get())); 3960b57cec5SDimitry Andric else 3970b57cec5SDimitry Andric Base = llvm::sys::path::parent_path(getDriver().getInstalledDir()); 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric Base += llvm::sys::path::get_separator(); 4000b57cec5SDimitry Andric findGccLibDir(); 4010b57cec5SDimitry Andric // GccLibDir must precede Base/lib so that the 4020b57cec5SDimitry Andric // correct crtbegin.o ,cetend.o would be found. 4030b57cec5SDimitry Andric getFilePaths().push_back(GccLibDir); 4040b57cec5SDimitry Andric getFilePaths().push_back( 4050b57cec5SDimitry Andric (Base + Arch + llvm::sys::path::get_separator() + "lib").str()); 4060b57cec5SDimitry Andric getFilePaths().push_back(Base + "lib"); 4070b57cec5SDimitry Andric // openSUSE 4080b57cec5SDimitry Andric getFilePaths().push_back(Base + Arch + "/sys-root/mingw/lib"); 4090b57cec5SDimitry Andric 4100b57cec5SDimitry Andric NativeLLVMSupport = 4110b57cec5SDimitry Andric Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER) 4120b57cec5SDimitry Andric .equals_lower("lld"); 4130b57cec5SDimitry Andric } 4140b57cec5SDimitry Andric 4150b57cec5SDimitry Andric bool toolchains::MinGW::IsIntegratedAssemblerDefault() const { return true; } 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric Tool *toolchains::MinGW::getTool(Action::ActionClass AC) const { 4180b57cec5SDimitry Andric switch (AC) { 4190b57cec5SDimitry Andric case Action::PreprocessJobClass: 4200b57cec5SDimitry Andric if (!Preprocessor) 4210b57cec5SDimitry Andric Preprocessor.reset(new tools::gcc::Preprocessor(*this)); 4220b57cec5SDimitry Andric return Preprocessor.get(); 4230b57cec5SDimitry Andric case Action::CompileJobClass: 4240b57cec5SDimitry Andric if (!Compiler) 4250b57cec5SDimitry Andric Compiler.reset(new tools::gcc::Compiler(*this)); 4260b57cec5SDimitry Andric return Compiler.get(); 4270b57cec5SDimitry Andric default: 4280b57cec5SDimitry Andric return ToolChain::getTool(AC); 4290b57cec5SDimitry Andric } 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric Tool *toolchains::MinGW::buildAssembler() const { 4330b57cec5SDimitry Andric return new tools::MinGW::Assembler(*this); 4340b57cec5SDimitry Andric } 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric Tool *toolchains::MinGW::buildLinker() const { 4370b57cec5SDimitry Andric return new tools::MinGW::Linker(*this); 4380b57cec5SDimitry Andric } 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric bool toolchains::MinGW::HasNativeLLVMSupport() const { 4410b57cec5SDimitry Andric return NativeLLVMSupport; 4420b57cec5SDimitry Andric } 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric bool toolchains::MinGW::IsUnwindTablesDefault(const ArgList &Args) const { 4450b57cec5SDimitry Andric Arg *ExceptionArg = Args.getLastArg(options::OPT_fsjlj_exceptions, 4460b57cec5SDimitry Andric options::OPT_fseh_exceptions, 4470b57cec5SDimitry Andric options::OPT_fdwarf_exceptions); 4480b57cec5SDimitry Andric if (ExceptionArg && 4490b57cec5SDimitry Andric ExceptionArg->getOption().matches(options::OPT_fseh_exceptions)) 4500b57cec5SDimitry Andric return true; 4510b57cec5SDimitry Andric return getArch() == llvm::Triple::x86_64 || 4520b57cec5SDimitry Andric getArch() == llvm::Triple::aarch64; 4530b57cec5SDimitry Andric } 4540b57cec5SDimitry Andric 4550b57cec5SDimitry Andric bool toolchains::MinGW::isPICDefault() const { 4560b57cec5SDimitry Andric return getArch() == llvm::Triple::x86_64; 4570b57cec5SDimitry Andric } 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric bool toolchains::MinGW::isPIEDefault() const { return false; } 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric bool toolchains::MinGW::isPICDefaultForced() const { 4620b57cec5SDimitry Andric return getArch() == llvm::Triple::x86_64; 4630b57cec5SDimitry Andric } 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric llvm::ExceptionHandling 4660b57cec5SDimitry Andric toolchains::MinGW::GetExceptionModel(const ArgList &Args) const { 4670b57cec5SDimitry Andric if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::aarch64) 4680b57cec5SDimitry Andric return llvm::ExceptionHandling::WinEH; 4690b57cec5SDimitry Andric return llvm::ExceptionHandling::DwarfCFI; 4700b57cec5SDimitry Andric } 4710b57cec5SDimitry Andric 4720b57cec5SDimitry Andric SanitizerMask toolchains::MinGW::getSupportedSanitizers() const { 4730b57cec5SDimitry Andric SanitizerMask Res = ToolChain::getSupportedSanitizers(); 4740b57cec5SDimitry Andric Res |= SanitizerKind::Address; 4750b57cec5SDimitry Andric Res |= SanitizerKind::PointerCompare; 4760b57cec5SDimitry Andric Res |= SanitizerKind::PointerSubtract; 4770b57cec5SDimitry Andric return Res; 4780b57cec5SDimitry Andric } 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs, 4810b57cec5SDimitry Andric ArgStringList &CC1Args) const { 4820b57cec5SDimitry Andric CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args); 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric void toolchains::MinGW::printVerboseInfo(raw_ostream &OS) const { 4860b57cec5SDimitry Andric CudaInstallation.print(OS); 4870b57cec5SDimitry Andric } 4880b57cec5SDimitry Andric 4890b57cec5SDimitry Andric // Include directories for various hosts: 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric // Windows, mingw.org 4920b57cec5SDimitry Andric // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++ 4930b57cec5SDimitry Andric // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\mingw32 4940b57cec5SDimitry Andric // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\backward 4950b57cec5SDimitry Andric // c:\mingw\include 4960b57cec5SDimitry Andric // c:\mingw\mingw32\include 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric // Windows, mingw-w64 mingw-builds 4990b57cec5SDimitry Andric // c:\mingw32\i686-w64-mingw32\include 5000b57cec5SDimitry Andric // c:\mingw32\i686-w64-mingw32\include\c++ 5010b57cec5SDimitry Andric // c:\mingw32\i686-w64-mingw32\include\c++\i686-w64-mingw32 5020b57cec5SDimitry Andric // c:\mingw32\i686-w64-mingw32\include\c++\backward 5030b57cec5SDimitry Andric 5040b57cec5SDimitry Andric // Windows, mingw-w64 msys2 5050b57cec5SDimitry Andric // c:\msys64\mingw32\include 5060b57cec5SDimitry Andric // c:\msys64\mingw32\i686-w64-mingw32\include 5070b57cec5SDimitry Andric // c:\msys64\mingw32\include\c++\4.9.2 5080b57cec5SDimitry Andric // c:\msys64\mingw32\include\c++\4.9.2\i686-w64-mingw32 5090b57cec5SDimitry Andric // c:\msys64\mingw32\include\c++\4.9.2\backward 5100b57cec5SDimitry Andric 5110b57cec5SDimitry Andric // openSUSE 5120b57cec5SDimitry Andric // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++ 5130b57cec5SDimitry Andric // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/x86_64-w64-mingw32 5140b57cec5SDimitry Andric // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/backward 5150b57cec5SDimitry Andric // /usr/x86_64-w64-mingw32/sys-root/mingw/include 5160b57cec5SDimitry Andric 5170b57cec5SDimitry Andric // Arch Linux 5180b57cec5SDimitry Andric // /usr/i686-w64-mingw32/include/c++/5.1.0 5190b57cec5SDimitry Andric // /usr/i686-w64-mingw32/include/c++/5.1.0/i686-w64-mingw32 5200b57cec5SDimitry Andric // /usr/i686-w64-mingw32/include/c++/5.1.0/backward 5210b57cec5SDimitry Andric // /usr/i686-w64-mingw32/include 5220b57cec5SDimitry Andric 5230b57cec5SDimitry Andric // Ubuntu 5240b57cec5SDimitry Andric // /usr/include/c++/4.8 5250b57cec5SDimitry Andric // /usr/include/c++/4.8/x86_64-w64-mingw32 5260b57cec5SDimitry Andric // /usr/include/c++/4.8/backward 5270b57cec5SDimitry Andric // /usr/x86_64-w64-mingw32/include 5280b57cec5SDimitry Andric 5290b57cec5SDimitry Andric void toolchains::MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 5300b57cec5SDimitry Andric ArgStringList &CC1Args) const { 5310b57cec5SDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdinc)) 5320b57cec5SDimitry Andric return; 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 5350b57cec5SDimitry Andric SmallString<1024> P(getDriver().ResourceDir); 5360b57cec5SDimitry Andric llvm::sys::path::append(P, "include"); 5370b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, P.str()); 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 5410b57cec5SDimitry Andric return; 5420b57cec5SDimitry Andric 5430b57cec5SDimitry Andric if (GetRuntimeLibType(DriverArgs) == ToolChain::RLT_Libgcc) { 5440b57cec5SDimitry Andric // openSUSE 5450b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, 5460b57cec5SDimitry Andric Base + Arch + "/sys-root/mingw/include"); 5470b57cec5SDimitry Andric } 5480b57cec5SDimitry Andric 5490b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, 5500b57cec5SDimitry Andric Base + Arch + llvm::sys::path::get_separator() + "include"); 5510b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, Base + "include"); 5520b57cec5SDimitry Andric } 5530b57cec5SDimitry Andric 5540b57cec5SDimitry Andric void toolchains::MinGW::AddClangCXXStdlibIncludeArgs( 5550b57cec5SDimitry Andric const ArgList &DriverArgs, ArgStringList &CC1Args) const { 5560b57cec5SDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdlibinc) || 5570b57cec5SDimitry Andric DriverArgs.hasArg(options::OPT_nostdincxx)) 5580b57cec5SDimitry Andric return; 5590b57cec5SDimitry Andric 5600b57cec5SDimitry Andric StringRef Slash = llvm::sys::path::get_separator(); 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric switch (GetCXXStdlibType(DriverArgs)) { 5630b57cec5SDimitry Andric case ToolChain::CST_Libcxx: 5640b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, Base + Arch + Slash + "include" + 5650b57cec5SDimitry Andric Slash + "c++" + Slash + "v1"); 5660b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, 5670b57cec5SDimitry Andric Base + "include" + Slash + "c++" + Slash + "v1"); 5680b57cec5SDimitry Andric break; 5690b57cec5SDimitry Andric 5700b57cec5SDimitry Andric case ToolChain::CST_Libstdcxx: 5710b57cec5SDimitry Andric llvm::SmallVector<llvm::SmallString<1024>, 4> CppIncludeBases; 5720b57cec5SDimitry Andric CppIncludeBases.emplace_back(Base); 5730b57cec5SDimitry Andric llvm::sys::path::append(CppIncludeBases[0], Arch, "include", "c++"); 5740b57cec5SDimitry Andric CppIncludeBases.emplace_back(Base); 5750b57cec5SDimitry Andric llvm::sys::path::append(CppIncludeBases[1], Arch, "include", "c++", Ver); 5760b57cec5SDimitry Andric CppIncludeBases.emplace_back(Base); 5770b57cec5SDimitry Andric llvm::sys::path::append(CppIncludeBases[2], "include", "c++", Ver); 5780b57cec5SDimitry Andric CppIncludeBases.emplace_back(GccLibDir); 5790b57cec5SDimitry Andric llvm::sys::path::append(CppIncludeBases[3], "include", "c++"); 5800b57cec5SDimitry Andric for (auto &CppIncludeBase : CppIncludeBases) { 5810b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, CppIncludeBase); 5820b57cec5SDimitry Andric CppIncludeBase += Slash; 5830b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + Arch); 5840b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + "backward"); 5850b57cec5SDimitry Andric } 5860b57cec5SDimitry Andric break; 5870b57cec5SDimitry Andric } 5880b57cec5SDimitry Andric } 589