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 "CommonArgs.h" 110b57cec5SDimitry Andric #include "clang/Config/config.h" 120b57cec5SDimitry Andric #include "clang/Driver/Compilation.h" 130b57cec5SDimitry Andric #include "clang/Driver/Driver.h" 140b57cec5SDimitry Andric #include "clang/Driver/DriverDiagnostic.h" 15fe6060f1SDimitry Andric #include "clang/Driver/InputInfo.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" 215ffd83dbSDimitry Andric #include "llvm/Support/VirtualFileSystem.h" 220b57cec5SDimitry Andric #include <system_error> 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric using namespace clang::diag; 250b57cec5SDimitry Andric using namespace clang::driver; 260b57cec5SDimitry Andric using namespace clang; 270b57cec5SDimitry Andric using namespace llvm::opt; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric /// MinGW Tools 300b57cec5SDimitry Andric void tools::MinGW::Assembler::ConstructJob(Compilation &C, const JobAction &JA, 310b57cec5SDimitry Andric const InputInfo &Output, 320b57cec5SDimitry Andric const InputInfoList &Inputs, 330b57cec5SDimitry Andric const ArgList &Args, 340b57cec5SDimitry Andric const char *LinkingOutput) const { 350b57cec5SDimitry Andric claimNoWarnArgs(Args); 360b57cec5SDimitry Andric ArgStringList CmdArgs; 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric if (getToolChain().getArch() == llvm::Triple::x86) { 390b57cec5SDimitry Andric CmdArgs.push_back("--32"); 400b57cec5SDimitry Andric } else if (getToolChain().getArch() == llvm::Triple::x86_64) { 410b57cec5SDimitry Andric CmdArgs.push_back("--64"); 420b57cec5SDimitry Andric } 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric CmdArgs.push_back("-o"); 470b57cec5SDimitry Andric CmdArgs.push_back(Output.getFilename()); 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric for (const auto &II : Inputs) 500b57cec5SDimitry Andric CmdArgs.push_back(II.getFilename()); 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); 535ffd83dbSDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), 54e8d8bef9SDimitry Andric Exec, CmdArgs, Inputs, Output)); 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric if (Args.hasArg(options::OPT_gsplit_dwarf)) 570b57cec5SDimitry Andric SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, 58e8d8bef9SDimitry Andric SplitDebugName(JA, Args, Inputs[0], Output)); 590b57cec5SDimitry Andric } 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric void tools::MinGW::Linker::AddLibGCC(const ArgList &Args, 620b57cec5SDimitry Andric ArgStringList &CmdArgs) const { 630b57cec5SDimitry Andric if (Args.hasArg(options::OPT_mthreads)) 640b57cec5SDimitry Andric CmdArgs.push_back("-lmingwthrd"); 650b57cec5SDimitry Andric CmdArgs.push_back("-lmingw32"); 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric // Make use of compiler-rt if --rtlib option is used 680b57cec5SDimitry Andric ToolChain::RuntimeLibType RLT = getToolChain().GetRuntimeLibType(Args); 690b57cec5SDimitry Andric if (RLT == ToolChain::RLT_Libgcc) { 700b57cec5SDimitry Andric bool Static = Args.hasArg(options::OPT_static_libgcc) || 710b57cec5SDimitry Andric Args.hasArg(options::OPT_static); 720b57cec5SDimitry Andric bool Shared = Args.hasArg(options::OPT_shared); 730b57cec5SDimitry Andric bool CXX = getToolChain().getDriver().CCCIsCXX(); 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric if (Static || (!CXX && !Shared)) { 760b57cec5SDimitry Andric CmdArgs.push_back("-lgcc"); 770b57cec5SDimitry Andric CmdArgs.push_back("-lgcc_eh"); 780b57cec5SDimitry Andric } else { 790b57cec5SDimitry Andric CmdArgs.push_back("-lgcc_s"); 800b57cec5SDimitry Andric CmdArgs.push_back("-lgcc"); 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric } else { 830b57cec5SDimitry Andric AddRunTimeLibs(getToolChain(), getToolChain().getDriver(), CmdArgs, Args); 840b57cec5SDimitry Andric } 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric CmdArgs.push_back("-lmoldname"); 870b57cec5SDimitry Andric CmdArgs.push_back("-lmingwex"); 880b57cec5SDimitry Andric for (auto Lib : Args.getAllArgValues(options::OPT_l)) 895f757f3fSDimitry Andric if (StringRef(Lib).starts_with("msvcr") || 905f757f3fSDimitry Andric StringRef(Lib).starts_with("ucrt") || 915f757f3fSDimitry Andric StringRef(Lib).starts_with("crtdll")) 920b57cec5SDimitry Andric return; 930b57cec5SDimitry Andric CmdArgs.push_back("-lmsvcrt"); 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, 970b57cec5SDimitry Andric const InputInfo &Output, 980b57cec5SDimitry Andric const InputInfoList &Inputs, 990b57cec5SDimitry Andric const ArgList &Args, 1000b57cec5SDimitry Andric const char *LinkingOutput) const { 1010b57cec5SDimitry Andric const ToolChain &TC = getToolChain(); 1020b57cec5SDimitry Andric const Driver &D = TC.getDriver(); 103349cc55cSDimitry Andric const SanitizerArgs &Sanitize = TC.getSanitizerArgs(Args); 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric ArgStringList CmdArgs; 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric // Silence warning for "clang -g foo.o -o foo" 1080b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_g_Group); 1090b57cec5SDimitry Andric // and "clang -emit-llvm foo.o -o foo" 1100b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_emit_llvm); 1110b57cec5SDimitry Andric // and for "clang -w foo.o -o foo". Other warning options are already 1120b57cec5SDimitry Andric // handled somewhere else. 1130b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_w); 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric if (!D.SysRoot.empty()) 1160b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric if (Args.hasArg(options::OPT_s)) 1190b57cec5SDimitry Andric CmdArgs.push_back("-s"); 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric CmdArgs.push_back("-m"); 1220b57cec5SDimitry Andric switch (TC.getArch()) { 1230b57cec5SDimitry Andric case llvm::Triple::x86: 1240b57cec5SDimitry Andric CmdArgs.push_back("i386pe"); 1250b57cec5SDimitry Andric break; 1260b57cec5SDimitry Andric case llvm::Triple::x86_64: 1270b57cec5SDimitry Andric CmdArgs.push_back("i386pep"); 1280b57cec5SDimitry Andric break; 1290b57cec5SDimitry Andric case llvm::Triple::arm: 1300b57cec5SDimitry Andric case llvm::Triple::thumb: 1310b57cec5SDimitry Andric // FIXME: this is incorrect for WinCE 1320b57cec5SDimitry Andric CmdArgs.push_back("thumb2pe"); 1330b57cec5SDimitry Andric break; 1340b57cec5SDimitry Andric case llvm::Triple::aarch64: 135*0fca6ea1SDimitry Andric if (TC.getEffectiveTriple().isWindowsArm64EC()) 136*0fca6ea1SDimitry Andric CmdArgs.push_back("arm64ecpe"); 137*0fca6ea1SDimitry Andric else 1380b57cec5SDimitry Andric CmdArgs.push_back("arm64pe"); 1390b57cec5SDimitry Andric break; 1400b57cec5SDimitry Andric default: 14106c3fb27SDimitry Andric D.Diag(diag::err_target_unknown_triple) << TC.getEffectiveTriple().str(); 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric 1446e75b2fbSDimitry Andric Arg *SubsysArg = 1456e75b2fbSDimitry Andric Args.getLastArg(options::OPT_mwindows, options::OPT_mconsole); 1466e75b2fbSDimitry Andric if (SubsysArg && SubsysArg->getOption().matches(options::OPT_mwindows)) { 1470b57cec5SDimitry Andric CmdArgs.push_back("--subsystem"); 1480b57cec5SDimitry Andric CmdArgs.push_back("windows"); 1496e75b2fbSDimitry Andric } else if (SubsysArg && 1506e75b2fbSDimitry Andric SubsysArg->getOption().matches(options::OPT_mconsole)) { 1510b57cec5SDimitry Andric CmdArgs.push_back("--subsystem"); 1520b57cec5SDimitry Andric CmdArgs.push_back("console"); 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric if (Args.hasArg(options::OPT_mdll)) 1560b57cec5SDimitry Andric CmdArgs.push_back("--dll"); 1570b57cec5SDimitry Andric else if (Args.hasArg(options::OPT_shared)) 1580b57cec5SDimitry Andric CmdArgs.push_back("--shared"); 1590b57cec5SDimitry Andric if (Args.hasArg(options::OPT_static)) 1600b57cec5SDimitry Andric CmdArgs.push_back("-Bstatic"); 1610b57cec5SDimitry Andric else 1620b57cec5SDimitry Andric CmdArgs.push_back("-Bdynamic"); 1630b57cec5SDimitry Andric if (Args.hasArg(options::OPT_mdll) || Args.hasArg(options::OPT_shared)) { 1640b57cec5SDimitry Andric CmdArgs.push_back("-e"); 1650b57cec5SDimitry Andric if (TC.getArch() == llvm::Triple::x86) 1660b57cec5SDimitry Andric CmdArgs.push_back("_DllMainCRTStartup@12"); 1670b57cec5SDimitry Andric else 1680b57cec5SDimitry Andric CmdArgs.push_back("DllMainCRTStartup"); 1690b57cec5SDimitry Andric CmdArgs.push_back("--enable-auto-image-base"); 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric 17204eeddc0SDimitry Andric if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) 17304eeddc0SDimitry Andric CmdArgs.push_back("--no-demangle"); 17404eeddc0SDimitry Andric 1755f757f3fSDimitry Andric if (!Args.hasFlag(options::OPT_fauto_import, options::OPT_fno_auto_import, 1765f757f3fSDimitry Andric true)) 1775f757f3fSDimitry Andric CmdArgs.push_back("--disable-auto-import"); 1785f757f3fSDimitry Andric 179bdd1243dSDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mguard_EQ)) { 180bdd1243dSDimitry Andric StringRef GuardArgs = A->getValue(); 181bdd1243dSDimitry Andric if (GuardArgs == "none") 182bdd1243dSDimitry Andric CmdArgs.push_back("--no-guard-cf"); 183bdd1243dSDimitry Andric else if (GuardArgs == "cf" || GuardArgs == "cf-nochecks") 184bdd1243dSDimitry Andric CmdArgs.push_back("--guard-cf"); 185bdd1243dSDimitry Andric else 186bdd1243dSDimitry Andric D.Diag(diag::err_drv_unsupported_option_argument) 187bdd1243dSDimitry Andric << A->getSpelling() << GuardArgs; 188bdd1243dSDimitry Andric } 189bdd1243dSDimitry Andric 1900b57cec5SDimitry Andric CmdArgs.push_back("-o"); 191480093f4SDimitry Andric const char *OutputFile = Output.getFilename(); 192480093f4SDimitry Andric // GCC implicitly adds an .exe extension if it is given an output file name 193e8d8bef9SDimitry Andric // that lacks an extension. 194e8d8bef9SDimitry Andric // GCC used to do this only when the compiler itself runs on windows, but 195e8d8bef9SDimitry Andric // since GCC 8 it does the same when cross compiling as well. 196e8d8bef9SDimitry Andric if (!llvm::sys::path::has_extension(OutputFile)) { 197480093f4SDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine(OutputFile) + ".exe")); 198e8d8bef9SDimitry Andric OutputFile = CmdArgs.back(); 199e8d8bef9SDimitry Andric } else 200480093f4SDimitry Andric CmdArgs.push_back(OutputFile); 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric // FIXME: add -N, -n flags 2030b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_r); 2040b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_s); 2050b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_t); 2060b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_u_Group); 2070b57cec5SDimitry Andric 2081ac55f4cSDimitry Andric // Add asan_dynamic as the first import lib before other libs. This allows 2091ac55f4cSDimitry Andric // asan to be initialized as early as possible to increase its instrumentation 2101ac55f4cSDimitry Andric // coverage to include other user DLLs which has not been built with asan. 2111ac55f4cSDimitry Andric if (Sanitize.needsAsanRt() && !Args.hasArg(options::OPT_nostdlib) && 2121ac55f4cSDimitry Andric !Args.hasArg(options::OPT_nodefaultlibs)) { 2131ac55f4cSDimitry Andric // MinGW always links against a shared MSVCRT. 2141ac55f4cSDimitry Andric CmdArgs.push_back( 2151ac55f4cSDimitry Andric TC.getCompilerRTArgString(Args, "asan_dynamic", ToolChain::FT_Shared)); 2161ac55f4cSDimitry Andric } 2171ac55f4cSDimitry Andric 2180b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { 2190b57cec5SDimitry Andric if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_mdll)) { 2200b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("dllcrt2.o"))); 2210b57cec5SDimitry Andric } else { 2220b57cec5SDimitry Andric if (Args.hasArg(options::OPT_municode)) 2230b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2u.o"))); 2240b57cec5SDimitry Andric else 2250b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2.o"))); 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric if (Args.hasArg(options::OPT_pg)) 2280b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("gcrt2.o"))); 2290b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o"))); 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_L); 2330b57cec5SDimitry Andric TC.AddFilePathLibArgs(Args, CmdArgs); 2345ffd83dbSDimitry Andric 2355ffd83dbSDimitry Andric // Add the compiler-rt library directories if they exist to help 2365ffd83dbSDimitry Andric // the linker find the various sanitizer, builtin, and profiling runtimes. 2375ffd83dbSDimitry Andric for (const auto &LibPath : TC.getLibraryPaths()) { 2385ffd83dbSDimitry Andric if (TC.getVFS().exists(LibPath)) 2395ffd83dbSDimitry Andric CmdArgs.push_back(Args.MakeArgString("-L" + LibPath)); 2405ffd83dbSDimitry Andric } 2415ffd83dbSDimitry Andric auto CRTPath = TC.getCompilerRTPath(); 2425ffd83dbSDimitry Andric if (TC.getVFS().exists(CRTPath)) 2435ffd83dbSDimitry Andric CmdArgs.push_back(Args.MakeArgString("-L" + CRTPath)); 2445ffd83dbSDimitry Andric 2450b57cec5SDimitry Andric AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); 2460b57cec5SDimitry Andric 2475f757f3fSDimitry Andric if (D.isUsingLTO()) { 2485f757f3fSDimitry Andric assert(!Inputs.empty() && "Must have at least one input."); 2495f757f3fSDimitry Andric addLTOOptions(TC, Args, CmdArgs, Output, Inputs[0], 2505f757f3fSDimitry Andric D.getLTOMode() == LTOK_Thin); 2515f757f3fSDimitry Andric } 2525f757f3fSDimitry Andric 25381ad6265SDimitry Andric if (C.getDriver().IsFlangMode()) { 25481ad6265SDimitry Andric addFortranRuntimeLibraryPath(TC, Args, CmdArgs); 2555f757f3fSDimitry Andric addFortranRuntimeLibs(TC, Args, CmdArgs); 25681ad6265SDimitry Andric } 25781ad6265SDimitry Andric 2580b57cec5SDimitry Andric // TODO: Add profile stuff here 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric if (TC.ShouldLinkCXXStdlib(Args)) { 2610b57cec5SDimitry Andric bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && 2620b57cec5SDimitry Andric !Args.hasArg(options::OPT_static); 2630b57cec5SDimitry Andric if (OnlyLibstdcxxStatic) 2640b57cec5SDimitry Andric CmdArgs.push_back("-Bstatic"); 2650b57cec5SDimitry Andric TC.AddCXXStdlibLibArgs(Args, CmdArgs); 2660b57cec5SDimitry Andric if (OnlyLibstdcxxStatic) 2670b57cec5SDimitry Andric CmdArgs.push_back("-Bdynamic"); 2680b57cec5SDimitry Andric } 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric bool HasWindowsApp = false; 2710b57cec5SDimitry Andric for (auto Lib : Args.getAllArgValues(options::OPT_l)) { 2720b57cec5SDimitry Andric if (Lib == "windowsapp") { 2730b57cec5SDimitry Andric HasWindowsApp = true; 2740b57cec5SDimitry Andric break; 2750b57cec5SDimitry Andric } 2760b57cec5SDimitry Andric } 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib)) { 2790b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nodefaultlibs)) { 2800b57cec5SDimitry Andric if (Args.hasArg(options::OPT_static)) 2810b57cec5SDimitry Andric CmdArgs.push_back("--start-group"); 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric if (Args.hasArg(options::OPT_fstack_protector) || 2840b57cec5SDimitry Andric Args.hasArg(options::OPT_fstack_protector_strong) || 2850b57cec5SDimitry Andric Args.hasArg(options::OPT_fstack_protector_all)) { 2860b57cec5SDimitry Andric CmdArgs.push_back("-lssp_nonshared"); 2870b57cec5SDimitry Andric CmdArgs.push_back("-lssp"); 2880b57cec5SDimitry Andric } 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, 2910b57cec5SDimitry Andric options::OPT_fno_openmp, false)) { 2920b57cec5SDimitry Andric switch (TC.getDriver().getOpenMPRuntime(Args)) { 2930b57cec5SDimitry Andric case Driver::OMPRT_OMP: 2940b57cec5SDimitry Andric CmdArgs.push_back("-lomp"); 2950b57cec5SDimitry Andric break; 2960b57cec5SDimitry Andric case Driver::OMPRT_IOMP5: 2970b57cec5SDimitry Andric CmdArgs.push_back("-liomp5md"); 2980b57cec5SDimitry Andric break; 2990b57cec5SDimitry Andric case Driver::OMPRT_GOMP: 3000b57cec5SDimitry Andric CmdArgs.push_back("-lgomp"); 3010b57cec5SDimitry Andric break; 3020b57cec5SDimitry Andric case Driver::OMPRT_Unknown: 3030b57cec5SDimitry Andric // Already diagnosed. 3040b57cec5SDimitry Andric break; 3050b57cec5SDimitry Andric } 3060b57cec5SDimitry Andric } 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric AddLibGCC(Args, CmdArgs); 3090b57cec5SDimitry Andric 3100b57cec5SDimitry Andric if (Args.hasArg(options::OPT_pg)) 3110b57cec5SDimitry Andric CmdArgs.push_back("-lgmon"); 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric if (Args.hasArg(options::OPT_pthread)) 3140b57cec5SDimitry Andric CmdArgs.push_back("-lpthread"); 3150b57cec5SDimitry Andric 3160b57cec5SDimitry Andric if (Sanitize.needsAsanRt()) { 3170b57cec5SDimitry Andric // MinGW always links against a shared MSVCRT. 3180b57cec5SDimitry Andric CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dynamic", 3190b57cec5SDimitry Andric ToolChain::FT_Shared)); 3200b57cec5SDimitry Andric CmdArgs.push_back( 3210b57cec5SDimitry Andric TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); 3220b57cec5SDimitry Andric CmdArgs.push_back("--require-defined"); 3230b57cec5SDimitry Andric CmdArgs.push_back(TC.getArch() == llvm::Triple::x86 3240b57cec5SDimitry Andric ? "___asan_seh_interceptor" 3250b57cec5SDimitry Andric : "__asan_seh_interceptor"); 3260b57cec5SDimitry Andric // Make sure the linker consider all object files from the dynamic 3270b57cec5SDimitry Andric // runtime thunk. 3280b57cec5SDimitry Andric CmdArgs.push_back("--whole-archive"); 3290b57cec5SDimitry Andric CmdArgs.push_back( 3300b57cec5SDimitry Andric TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); 3310b57cec5SDimitry Andric CmdArgs.push_back("--no-whole-archive"); 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric 3340b57cec5SDimitry Andric TC.addProfileRTLibs(Args, CmdArgs); 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric if (!HasWindowsApp) { 3370b57cec5SDimitry Andric // Add system libraries. If linking to libwindowsapp.a, that import 3380b57cec5SDimitry Andric // library replaces all these and we shouldn't accidentally try to 3390b57cec5SDimitry Andric // link to the normal desktop mode dlls. 3400b57cec5SDimitry Andric if (Args.hasArg(options::OPT_mwindows)) { 3410b57cec5SDimitry Andric CmdArgs.push_back("-lgdi32"); 3420b57cec5SDimitry Andric CmdArgs.push_back("-lcomdlg32"); 3430b57cec5SDimitry Andric } 3440b57cec5SDimitry Andric CmdArgs.push_back("-ladvapi32"); 3450b57cec5SDimitry Andric CmdArgs.push_back("-lshell32"); 3460b57cec5SDimitry Andric CmdArgs.push_back("-luser32"); 3470b57cec5SDimitry Andric CmdArgs.push_back("-lkernel32"); 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric 3505ffd83dbSDimitry Andric if (Args.hasArg(options::OPT_static)) { 3510b57cec5SDimitry Andric CmdArgs.push_back("--end-group"); 3525ffd83dbSDimitry Andric } else { 3530b57cec5SDimitry Andric AddLibGCC(Args, CmdArgs); 3545ffd83dbSDimitry Andric if (!HasWindowsApp) 3555ffd83dbSDimitry Andric CmdArgs.push_back("-lkernel32"); 3565ffd83dbSDimitry Andric } 3570b57cec5SDimitry Andric } 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostartfiles)) { 3600b57cec5SDimitry Andric // Add crtfastmath.o if available and fast math is enabled. 3615ffd83dbSDimitry Andric TC.addFastMathRuntimeIfAvailable(Args, CmdArgs); 3620b57cec5SDimitry Andric 3630b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o"))); 3640b57cec5SDimitry Andric } 3650b57cec5SDimitry Andric } 3660b57cec5SDimitry Andric const char *Exec = Args.MakeArgString(TC.GetLinkerPath()); 367e8d8bef9SDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, 368e8d8bef9SDimitry Andric ResponseFileSupport::AtFileUTF8(), 369e8d8bef9SDimitry Andric Exec, CmdArgs, Inputs, Output)); 3700b57cec5SDimitry Andric } 3710b57cec5SDimitry Andric 372bdd1243dSDimitry Andric static bool isCrossCompiling(const llvm::Triple &T, bool RequireArchMatch) { 373bdd1243dSDimitry Andric llvm::Triple HostTriple(llvm::Triple::normalize(LLVM_HOST_TRIPLE)); 374bdd1243dSDimitry Andric if (HostTriple.getOS() != llvm::Triple::Win32) 375bdd1243dSDimitry Andric return true; 376bdd1243dSDimitry Andric if (RequireArchMatch && HostTriple.getArch() != T.getArch()) 377bdd1243dSDimitry Andric return true; 378bdd1243dSDimitry Andric return false; 379bdd1243dSDimitry Andric } 380bdd1243dSDimitry Andric 3810b57cec5SDimitry Andric // Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple. 3820b57cec5SDimitry Andric static bool findGccVersion(StringRef LibDir, std::string &GccLibDir, 383753f127fSDimitry Andric std::string &Ver, 384753f127fSDimitry Andric toolchains::Generic_GCC::GCCVersion &Version) { 385753f127fSDimitry Andric Version = toolchains::Generic_GCC::GCCVersion::Parse("0.0.0"); 3860b57cec5SDimitry Andric std::error_code EC; 3870b57cec5SDimitry Andric for (llvm::sys::fs::directory_iterator LI(LibDir, EC), LE; !EC && LI != LE; 3880b57cec5SDimitry Andric LI = LI.increment(EC)) { 3890b57cec5SDimitry Andric StringRef VersionText = llvm::sys::path::filename(LI->path()); 3900b57cec5SDimitry Andric auto CandidateVersion = 3910b57cec5SDimitry Andric toolchains::Generic_GCC::GCCVersion::Parse(VersionText); 3920b57cec5SDimitry Andric if (CandidateVersion.Major == -1) 3930b57cec5SDimitry Andric continue; 3940b57cec5SDimitry Andric if (CandidateVersion <= Version) 3950b57cec5SDimitry Andric continue; 396fe6060f1SDimitry Andric Version = CandidateVersion; 3975ffd83dbSDimitry Andric Ver = std::string(VersionText); 3980b57cec5SDimitry Andric GccLibDir = LI->path(); 3990b57cec5SDimitry Andric } 4000b57cec5SDimitry Andric return Ver.size(); 4010b57cec5SDimitry Andric } 4020b57cec5SDimitry Andric 403bdd1243dSDimitry Andric static llvm::Triple getLiteralTriple(const Driver &D, const llvm::Triple &T) { 404bdd1243dSDimitry Andric llvm::Triple LiteralTriple(D.getTargetTriple()); 405bdd1243dSDimitry Andric // The arch portion of the triple may be overridden by -m32/-m64. 406bdd1243dSDimitry Andric LiteralTriple.setArchName(T.getArchName()); 407bdd1243dSDimitry Andric return LiteralTriple; 408bdd1243dSDimitry Andric } 409bdd1243dSDimitry Andric 410bdd1243dSDimitry Andric void toolchains::MinGW::findGccLibDir(const llvm::Triple &LiteralTriple) { 411bdd1243dSDimitry Andric llvm::SmallVector<llvm::SmallString<32>, 5> SubdirNames; 412bdd1243dSDimitry Andric SubdirNames.emplace_back(LiteralTriple.str()); 413bdd1243dSDimitry Andric SubdirNames.emplace_back(getTriple().str()); 414349cc55cSDimitry Andric SubdirNames.emplace_back(getTriple().getArchName()); 415bdd1243dSDimitry Andric SubdirNames.back() += "-w64-mingw32"; 416bdd1243dSDimitry Andric SubdirNames.emplace_back(getTriple().getArchName()); 417bdd1243dSDimitry Andric SubdirNames.back() += "-w64-mingw32ucrt"; 418349cc55cSDimitry Andric SubdirNames.emplace_back("mingw32"); 419bdd1243dSDimitry Andric if (SubdirName.empty()) { 420bdd1243dSDimitry Andric SubdirName = getTriple().getArchName(); 421bdd1243dSDimitry Andric SubdirName += "-w64-mingw32"; 422bdd1243dSDimitry Andric } 4230b57cec5SDimitry Andric // lib: Arch Linux, Ubuntu, Windows 4240b57cec5SDimitry Andric // lib64: openSUSE Linux 4250b57cec5SDimitry Andric for (StringRef CandidateLib : {"lib", "lib64"}) { 426349cc55cSDimitry Andric for (StringRef CandidateSysroot : SubdirNames) { 4270b57cec5SDimitry Andric llvm::SmallString<1024> LibDir(Base); 428349cc55cSDimitry Andric llvm::sys::path::append(LibDir, CandidateLib, "gcc", CandidateSysroot); 429753f127fSDimitry Andric if (findGccVersion(LibDir, GccLibDir, Ver, GccVer)) { 430349cc55cSDimitry Andric SubdirName = std::string(CandidateSysroot); 4310b57cec5SDimitry Andric return; 4320b57cec5SDimitry Andric } 4330b57cec5SDimitry Andric } 4340b57cec5SDimitry Andric } 4350b57cec5SDimitry Andric } 4360b57cec5SDimitry Andric 437bdd1243dSDimitry Andric static llvm::ErrorOr<std::string> findGcc(const llvm::Triple &LiteralTriple, 438bdd1243dSDimitry Andric const llvm::Triple &T) { 439bdd1243dSDimitry Andric llvm::SmallVector<llvm::SmallString<32>, 5> Gccs; 440bdd1243dSDimitry Andric Gccs.emplace_back(LiteralTriple.str()); 441bdd1243dSDimitry Andric Gccs.back() += "-gcc"; 442bdd1243dSDimitry Andric Gccs.emplace_back(T.str()); 443bdd1243dSDimitry Andric Gccs.back() += "-gcc"; 444349cc55cSDimitry Andric Gccs.emplace_back(T.getArchName()); 445bdd1243dSDimitry Andric Gccs.back() += "-w64-mingw32-gcc"; 446bdd1243dSDimitry Andric Gccs.emplace_back(T.getArchName()); 447bdd1243dSDimitry Andric Gccs.back() += "-w64-mingw32ucrt-gcc"; 4480b57cec5SDimitry Andric Gccs.emplace_back("mingw32-gcc"); 4490b57cec5SDimitry Andric // Please do not add "gcc" here 4500b57cec5SDimitry Andric for (StringRef CandidateGcc : Gccs) 4510b57cec5SDimitry Andric if (llvm::ErrorOr<std::string> GPPName = llvm::sys::findProgramByName(CandidateGcc)) 4520b57cec5SDimitry Andric return GPPName; 4530b57cec5SDimitry Andric return make_error_code(std::errc::no_such_file_or_directory); 4540b57cec5SDimitry Andric } 4550b57cec5SDimitry Andric 456349cc55cSDimitry Andric static llvm::ErrorOr<std::string> 457bdd1243dSDimitry Andric findClangRelativeSysroot(const Driver &D, const llvm::Triple &LiteralTriple, 458bdd1243dSDimitry Andric const llvm::Triple &T, std::string &SubdirName) { 459bdd1243dSDimitry Andric llvm::SmallVector<llvm::SmallString<32>, 4> Subdirs; 460bdd1243dSDimitry Andric Subdirs.emplace_back(LiteralTriple.str()); 461349cc55cSDimitry Andric Subdirs.emplace_back(T.str()); 462349cc55cSDimitry Andric Subdirs.emplace_back(T.getArchName()); 463bdd1243dSDimitry Andric Subdirs.back() += "-w64-mingw32"; 464bdd1243dSDimitry Andric Subdirs.emplace_back(T.getArchName()); 465bdd1243dSDimitry Andric Subdirs.back() += "-w64-mingw32ucrt"; 466*0fca6ea1SDimitry Andric StringRef ClangRoot = llvm::sys::path::parent_path(D.Dir); 4670b57cec5SDimitry Andric StringRef Sep = llvm::sys::path::get_separator(); 4680b57cec5SDimitry Andric for (StringRef CandidateSubdir : Subdirs) { 4690b57cec5SDimitry Andric if (llvm::sys::fs::is_directory(ClangRoot + Sep + CandidateSubdir)) { 470349cc55cSDimitry Andric SubdirName = std::string(CandidateSubdir); 4710b57cec5SDimitry Andric return (ClangRoot + Sep + CandidateSubdir).str(); 4720b57cec5SDimitry Andric } 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric return make_error_code(std::errc::no_such_file_or_directory); 4750b57cec5SDimitry Andric } 4760b57cec5SDimitry Andric 4771db9f3b2SDimitry Andric static bool looksLikeMinGWSysroot(const std::string &Directory) { 4781db9f3b2SDimitry Andric StringRef Sep = llvm::sys::path::get_separator(); 4791db9f3b2SDimitry Andric if (!llvm::sys::fs::exists(Directory + Sep + "include" + Sep + "_mingw.h")) 4801db9f3b2SDimitry Andric return false; 4811db9f3b2SDimitry Andric if (!llvm::sys::fs::exists(Directory + Sep + "lib" + Sep + "libkernel32.a")) 4821db9f3b2SDimitry Andric return false; 4831db9f3b2SDimitry Andric return true; 4841db9f3b2SDimitry Andric } 4851db9f3b2SDimitry Andric 4860b57cec5SDimitry Andric toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, 4870b57cec5SDimitry Andric const ArgList &Args) 4885ffd83dbSDimitry Andric : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args), 4895ffd83dbSDimitry Andric RocmInstallation(D, Triple, Args) { 490*0fca6ea1SDimitry Andric getProgramPaths().push_back(getDriver().Dir); 4910b57cec5SDimitry Andric 4921db9f3b2SDimitry Andric std::string InstallBase = 493*0fca6ea1SDimitry Andric std::string(llvm::sys::path::parent_path(getDriver().Dir)); 494349cc55cSDimitry Andric // The sequence for detecting a sysroot here should be kept in sync with 495349cc55cSDimitry Andric // the testTriple function below. 496bdd1243dSDimitry Andric llvm::Triple LiteralTriple = getLiteralTriple(D, getTriple()); 4970b57cec5SDimitry Andric if (getDriver().SysRoot.size()) 4980b57cec5SDimitry Andric Base = getDriver().SysRoot; 4990b57cec5SDimitry Andric // Look for <clang-bin>/../<triplet>; if found, use <clang-bin>/.. as the 5000b57cec5SDimitry Andric // base as it could still be a base for a gcc setup with libgcc. 501bdd1243dSDimitry Andric else if (llvm::ErrorOr<std::string> TargetSubdir = findClangRelativeSysroot( 502bdd1243dSDimitry Andric getDriver(), LiteralTriple, getTriple(), SubdirName)) 5035ffd83dbSDimitry Andric Base = std::string(llvm::sys::path::parent_path(TargetSubdir.get())); 5041db9f3b2SDimitry Andric // If the install base of Clang seems to have mingw sysroot files directly 5051db9f3b2SDimitry Andric // in the toplevel include and lib directories, use this as base instead of 5061db9f3b2SDimitry Andric // looking for a triple prefixed GCC in the path. 5071db9f3b2SDimitry Andric else if (looksLikeMinGWSysroot(InstallBase)) 5081db9f3b2SDimitry Andric Base = InstallBase; 509bdd1243dSDimitry Andric else if (llvm::ErrorOr<std::string> GPPName = 510bdd1243dSDimitry Andric findGcc(LiteralTriple, getTriple())) 5115ffd83dbSDimitry Andric Base = std::string(llvm::sys::path::parent_path( 5125ffd83dbSDimitry Andric llvm::sys::path::parent_path(GPPName.get()))); 5130b57cec5SDimitry Andric else 5141db9f3b2SDimitry Andric Base = InstallBase; 5150b57cec5SDimitry Andric 5160b57cec5SDimitry Andric Base += llvm::sys::path::get_separator(); 517bdd1243dSDimitry Andric findGccLibDir(LiteralTriple); 518bdd1243dSDimitry Andric TripleDirName = SubdirName; 5190b57cec5SDimitry Andric // GccLibDir must precede Base/lib so that the 5200b57cec5SDimitry Andric // correct crtbegin.o ,cetend.o would be found. 5210b57cec5SDimitry Andric getFilePaths().push_back(GccLibDir); 522bdd1243dSDimitry Andric 523bdd1243dSDimitry Andric // openSUSE/Fedora 524bdd1243dSDimitry Andric std::string CandidateSubdir = SubdirName + "/sys-root/mingw"; 525bdd1243dSDimitry Andric if (getDriver().getVFS().exists(Base + CandidateSubdir)) 526bdd1243dSDimitry Andric SubdirName = CandidateSubdir; 527bdd1243dSDimitry Andric 5280b57cec5SDimitry Andric getFilePaths().push_back( 529349cc55cSDimitry Andric (Base + SubdirName + llvm::sys::path::get_separator() + "lib").str()); 530753f127fSDimitry Andric 531753f127fSDimitry Andric // Gentoo 532753f127fSDimitry Andric getFilePaths().push_back( 533753f127fSDimitry Andric (Base + SubdirName + llvm::sys::path::get_separator() + "mingw/lib").str()); 534753f127fSDimitry Andric 535bdd1243dSDimitry Andric // Only include <base>/lib if we're not cross compiling (not even for 536bdd1243dSDimitry Andric // windows->windows to a different arch), or if the sysroot has been set 537bdd1243dSDimitry Andric // (where we presume the user has pointed it at an arch specific 538bdd1243dSDimitry Andric // subdirectory). 539bdd1243dSDimitry Andric if (!::isCrossCompiling(getTriple(), /*RequireArchMatch=*/true) || 540bdd1243dSDimitry Andric getDriver().SysRoot.size()) 5410b57cec5SDimitry Andric getFilePaths().push_back(Base + "lib"); 5420b57cec5SDimitry Andric 5430b57cec5SDimitry Andric NativeLLVMSupport = 5440b57cec5SDimitry Andric Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER) 545fe6060f1SDimitry Andric .equals_insensitive("lld"); 5460b57cec5SDimitry Andric } 5470b57cec5SDimitry Andric 5480b57cec5SDimitry Andric Tool *toolchains::MinGW::getTool(Action::ActionClass AC) const { 5490b57cec5SDimitry Andric switch (AC) { 5500b57cec5SDimitry Andric case Action::PreprocessJobClass: 5510b57cec5SDimitry Andric if (!Preprocessor) 5520b57cec5SDimitry Andric Preprocessor.reset(new tools::gcc::Preprocessor(*this)); 5530b57cec5SDimitry Andric return Preprocessor.get(); 5540b57cec5SDimitry Andric case Action::CompileJobClass: 5550b57cec5SDimitry Andric if (!Compiler) 5560b57cec5SDimitry Andric Compiler.reset(new tools::gcc::Compiler(*this)); 5570b57cec5SDimitry Andric return Compiler.get(); 5580b57cec5SDimitry Andric default: 5590b57cec5SDimitry Andric return ToolChain::getTool(AC); 5600b57cec5SDimitry Andric } 5610b57cec5SDimitry Andric } 5620b57cec5SDimitry Andric 5630b57cec5SDimitry Andric Tool *toolchains::MinGW::buildAssembler() const { 5640b57cec5SDimitry Andric return new tools::MinGW::Assembler(*this); 5650b57cec5SDimitry Andric } 5660b57cec5SDimitry Andric 5670b57cec5SDimitry Andric Tool *toolchains::MinGW::buildLinker() const { 5680b57cec5SDimitry Andric return new tools::MinGW::Linker(*this); 5690b57cec5SDimitry Andric } 5700b57cec5SDimitry Andric 5710b57cec5SDimitry Andric bool toolchains::MinGW::HasNativeLLVMSupport() const { 5720b57cec5SDimitry Andric return NativeLLVMSupport; 5730b57cec5SDimitry Andric } 5740b57cec5SDimitry Andric 575bdd1243dSDimitry Andric ToolChain::UnwindTableLevel 576bdd1243dSDimitry Andric toolchains::MinGW::getDefaultUnwindTableLevel(const ArgList &Args) const { 5770b57cec5SDimitry Andric Arg *ExceptionArg = Args.getLastArg(options::OPT_fsjlj_exceptions, 5780b57cec5SDimitry Andric options::OPT_fseh_exceptions, 5790b57cec5SDimitry Andric options::OPT_fdwarf_exceptions); 5800b57cec5SDimitry Andric if (ExceptionArg && 5810b57cec5SDimitry Andric ExceptionArg->getOption().matches(options::OPT_fseh_exceptions)) 582bdd1243dSDimitry Andric return UnwindTableLevel::Asynchronous; 583bdd1243dSDimitry Andric 584bdd1243dSDimitry Andric if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::arm || 585bdd1243dSDimitry Andric getArch() == llvm::Triple::thumb || getArch() == llvm::Triple::aarch64) 586bdd1243dSDimitry Andric return UnwindTableLevel::Asynchronous; 587bdd1243dSDimitry Andric return UnwindTableLevel::None; 5880b57cec5SDimitry Andric } 5890b57cec5SDimitry Andric 5900b57cec5SDimitry Andric bool toolchains::MinGW::isPICDefault() const { 591349cc55cSDimitry Andric return getArch() == llvm::Triple::x86_64 || 592349cc55cSDimitry Andric getArch() == llvm::Triple::aarch64; 5930b57cec5SDimitry Andric } 5940b57cec5SDimitry Andric 595349cc55cSDimitry Andric bool toolchains::MinGW::isPIEDefault(const llvm::opt::ArgList &Args) const { 596349cc55cSDimitry Andric return false; 597349cc55cSDimitry Andric } 5980b57cec5SDimitry Andric 59904eeddc0SDimitry Andric bool toolchains::MinGW::isPICDefaultForced() const { return true; } 6000b57cec5SDimitry Andric 6010b57cec5SDimitry Andric llvm::ExceptionHandling 6020b57cec5SDimitry Andric toolchains::MinGW::GetExceptionModel(const ArgList &Args) const { 60381ad6265SDimitry Andric if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::aarch64 || 60481ad6265SDimitry Andric getArch() == llvm::Triple::arm || getArch() == llvm::Triple::thumb) 6050b57cec5SDimitry Andric return llvm::ExceptionHandling::WinEH; 6060b57cec5SDimitry Andric return llvm::ExceptionHandling::DwarfCFI; 6070b57cec5SDimitry Andric } 6080b57cec5SDimitry Andric 6090b57cec5SDimitry Andric SanitizerMask toolchains::MinGW::getSupportedSanitizers() const { 6100b57cec5SDimitry Andric SanitizerMask Res = ToolChain::getSupportedSanitizers(); 6110b57cec5SDimitry Andric Res |= SanitizerKind::Address; 6120b57cec5SDimitry Andric Res |= SanitizerKind::PointerCompare; 6130b57cec5SDimitry Andric Res |= SanitizerKind::PointerSubtract; 614e8d8bef9SDimitry Andric Res |= SanitizerKind::Vptr; 6150b57cec5SDimitry Andric return Res; 6160b57cec5SDimitry Andric } 6170b57cec5SDimitry Andric 6180b57cec5SDimitry Andric void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs, 6190b57cec5SDimitry Andric ArgStringList &CC1Args) const { 6207a6dacacSDimitry Andric CudaInstallation->AddCudaIncludeArgs(DriverArgs, CC1Args); 6210b57cec5SDimitry Andric } 6220b57cec5SDimitry Andric 6235ffd83dbSDimitry Andric void toolchains::MinGW::AddHIPIncludeArgs(const ArgList &DriverArgs, 6245ffd83dbSDimitry Andric ArgStringList &CC1Args) const { 6257a6dacacSDimitry Andric RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args); 6265ffd83dbSDimitry Andric } 6275ffd83dbSDimitry Andric 6280b57cec5SDimitry Andric void toolchains::MinGW::printVerboseInfo(raw_ostream &OS) const { 6297a6dacacSDimitry Andric CudaInstallation->print(OS); 6307a6dacacSDimitry Andric RocmInstallation->print(OS); 6310b57cec5SDimitry Andric } 6320b57cec5SDimitry Andric 6330b57cec5SDimitry Andric // Include directories for various hosts: 6340b57cec5SDimitry Andric 6350b57cec5SDimitry Andric // Windows, mingw.org 6360b57cec5SDimitry Andric // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++ 6370b57cec5SDimitry Andric // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\mingw32 6380b57cec5SDimitry Andric // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\backward 6390b57cec5SDimitry Andric // c:\mingw\include 6400b57cec5SDimitry Andric // c:\mingw\mingw32\include 6410b57cec5SDimitry Andric 6420b57cec5SDimitry Andric // Windows, mingw-w64 mingw-builds 6430b57cec5SDimitry Andric // c:\mingw32\i686-w64-mingw32\include 6440b57cec5SDimitry Andric // c:\mingw32\i686-w64-mingw32\include\c++ 6450b57cec5SDimitry Andric // c:\mingw32\i686-w64-mingw32\include\c++\i686-w64-mingw32 6460b57cec5SDimitry Andric // c:\mingw32\i686-w64-mingw32\include\c++\backward 6470b57cec5SDimitry Andric 6480b57cec5SDimitry Andric // Windows, mingw-w64 msys2 6490b57cec5SDimitry Andric // c:\msys64\mingw32\include 6500b57cec5SDimitry Andric // c:\msys64\mingw32\i686-w64-mingw32\include 6510b57cec5SDimitry Andric // c:\msys64\mingw32\include\c++\4.9.2 6520b57cec5SDimitry Andric // c:\msys64\mingw32\include\c++\4.9.2\i686-w64-mingw32 6530b57cec5SDimitry Andric // c:\msys64\mingw32\include\c++\4.9.2\backward 6540b57cec5SDimitry Andric 6550b57cec5SDimitry Andric // openSUSE 6560b57cec5SDimitry Andric // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++ 6570b57cec5SDimitry Andric // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/x86_64-w64-mingw32 6580b57cec5SDimitry Andric // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/backward 6590b57cec5SDimitry Andric // /usr/x86_64-w64-mingw32/sys-root/mingw/include 6600b57cec5SDimitry Andric 6610b57cec5SDimitry Andric // Arch Linux 6620b57cec5SDimitry Andric // /usr/i686-w64-mingw32/include/c++/5.1.0 6630b57cec5SDimitry Andric // /usr/i686-w64-mingw32/include/c++/5.1.0/i686-w64-mingw32 6640b57cec5SDimitry Andric // /usr/i686-w64-mingw32/include/c++/5.1.0/backward 6650b57cec5SDimitry Andric // /usr/i686-w64-mingw32/include 6660b57cec5SDimitry Andric 6670b57cec5SDimitry Andric // Ubuntu 6680b57cec5SDimitry Andric // /usr/include/c++/4.8 6690b57cec5SDimitry Andric // /usr/include/c++/4.8/x86_64-w64-mingw32 6700b57cec5SDimitry Andric // /usr/include/c++/4.8/backward 6710b57cec5SDimitry Andric // /usr/x86_64-w64-mingw32/include 6720b57cec5SDimitry Andric 673bdd1243dSDimitry Andric // Fedora 674bdd1243dSDimitry Andric // /usr/x86_64-w64-mingw32ucrt/sys-root/mingw/include/c++/x86_64-w64-mingw32ucrt 675bdd1243dSDimitry Andric // /usr/x86_64-w64-mingw32ucrt/sys-root/mingw/include/c++/backward 676bdd1243dSDimitry Andric // /usr/x86_64-w64-mingw32ucrt/sys-root/mingw/include 677bdd1243dSDimitry Andric // /usr/lib/gcc/x86_64-w64-mingw32ucrt/12.2.1/include-fixed 678bdd1243dSDimitry Andric 6790b57cec5SDimitry Andric void toolchains::MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 6800b57cec5SDimitry Andric ArgStringList &CC1Args) const { 6810b57cec5SDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdinc)) 6820b57cec5SDimitry Andric return; 6830b57cec5SDimitry Andric 6840b57cec5SDimitry Andric if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 6850b57cec5SDimitry Andric SmallString<1024> P(getDriver().ResourceDir); 6860b57cec5SDimitry Andric llvm::sys::path::append(P, "include"); 6870b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, P.str()); 6880b57cec5SDimitry Andric } 6890b57cec5SDimitry Andric 6900b57cec5SDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 6910b57cec5SDimitry Andric return; 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, 694349cc55cSDimitry Andric Base + SubdirName + llvm::sys::path::get_separator() + 695349cc55cSDimitry Andric "include"); 696753f127fSDimitry Andric 697753f127fSDimitry Andric // Gentoo 698753f127fSDimitry Andric addSystemInclude(DriverArgs, CC1Args, 699753f127fSDimitry Andric Base + SubdirName + llvm::sys::path::get_separator() + "usr/include"); 700753f127fSDimitry Andric 701bdd1243dSDimitry Andric // Only include <base>/include if we're not cross compiling (but do allow it 702bdd1243dSDimitry Andric // if we're on Windows and building for Windows on another architecture), 703bdd1243dSDimitry Andric // or if the sysroot has been set (where we presume the user has pointed it 704bdd1243dSDimitry Andric // at an arch specific subdirectory). 705bdd1243dSDimitry Andric if (!::isCrossCompiling(getTriple(), /*RequireArchMatch=*/false) || 706bdd1243dSDimitry Andric getDriver().SysRoot.size()) 7070b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, Base + "include"); 7080b57cec5SDimitry Andric } 7090b57cec5SDimitry Andric 710bdd1243dSDimitry Andric void toolchains::MinGW::addClangTargetOptions( 711bdd1243dSDimitry Andric const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, 712bdd1243dSDimitry Andric Action::OffloadKind DeviceOffloadKind) const { 713bdd1243dSDimitry Andric if (Arg *A = DriverArgs.getLastArg(options::OPT_mguard_EQ)) { 714bdd1243dSDimitry Andric StringRef GuardArgs = A->getValue(); 715bdd1243dSDimitry Andric if (GuardArgs == "none") { 716bdd1243dSDimitry Andric // Do nothing. 717bdd1243dSDimitry Andric } else if (GuardArgs == "cf") { 718bdd1243dSDimitry Andric // Emit CFG instrumentation and the table of address-taken functions. 719bdd1243dSDimitry Andric CC1Args.push_back("-cfguard"); 720bdd1243dSDimitry Andric } else if (GuardArgs == "cf-nochecks") { 721bdd1243dSDimitry Andric // Emit only the table of address-taken functions. 722bdd1243dSDimitry Andric CC1Args.push_back("-cfguard-no-checks"); 723bdd1243dSDimitry Andric } else { 724bdd1243dSDimitry Andric getDriver().Diag(diag::err_drv_unsupported_option_argument) 725bdd1243dSDimitry Andric << A->getSpelling() << GuardArgs; 726bdd1243dSDimitry Andric } 727bdd1243dSDimitry Andric } 72806c3fb27SDimitry Andric 729*0fca6ea1SDimitry Andric // Default to not enabling sized deallocation, but let user provided options 730*0fca6ea1SDimitry Andric // override it. 731*0fca6ea1SDimitry Andric // 732*0fca6ea1SDimitry Andric // If using sized deallocation, user code that invokes delete will end up 733*0fca6ea1SDimitry Andric // calling delete(void*,size_t). If the user wanted to override the 734*0fca6ea1SDimitry Andric // operator delete(void*), there may be a fallback operator 735*0fca6ea1SDimitry Andric // delete(void*,size_t) which calls the regular operator delete(void*). 736*0fca6ea1SDimitry Andric // 737*0fca6ea1SDimitry Andric // However, if the C++ standard library is linked in the form of a DLL, 738*0fca6ea1SDimitry Andric // and the fallback operator delete(void*,size_t) is within this DLL (which is 739*0fca6ea1SDimitry Andric // the case for libc++ at least) it will only redirect towards the library's 740*0fca6ea1SDimitry Andric // default operator delete(void*), not towards the user's provided operator 741*0fca6ea1SDimitry Andric // delete(void*). 742*0fca6ea1SDimitry Andric // 743*0fca6ea1SDimitry Andric // This issue can be avoided, if the fallback operators are linked statically 744*0fca6ea1SDimitry Andric // into the callers, even if the C++ standard library is linked as a DLL. 745*0fca6ea1SDimitry Andric // 746*0fca6ea1SDimitry Andric // This is meant as a temporary workaround until libc++ implements this 747*0fca6ea1SDimitry Andric // technique, which is tracked in 748*0fca6ea1SDimitry Andric // https://github.com/llvm/llvm-project/issues/96899. 749*0fca6ea1SDimitry Andric if (!DriverArgs.hasArgNoClaim(options::OPT_fsized_deallocation, 750*0fca6ea1SDimitry Andric options::OPT_fno_sized_deallocation)) 751*0fca6ea1SDimitry Andric CC1Args.push_back("-fno-sized-deallocation"); 752*0fca6ea1SDimitry Andric 753bdb86d1aSDimitry Andric CC1Args.push_back("-fno-use-init-array"); 754bdb86d1aSDimitry Andric 7553bd749dbSDimitry Andric for (auto Opt : {options::OPT_mthreads, options::OPT_mwindows, 7563bd749dbSDimitry Andric options::OPT_mconsole, options::OPT_mdll}) { 7573bd749dbSDimitry Andric if (Arg *A = DriverArgs.getLastArgNoClaim(Opt)) 75806c3fb27SDimitry Andric A->ignoreTargetSpecific(); 759bdd1243dSDimitry Andric } 7603bd749dbSDimitry Andric } 761bdd1243dSDimitry Andric 7620b57cec5SDimitry Andric void toolchains::MinGW::AddClangCXXStdlibIncludeArgs( 7630b57cec5SDimitry Andric const ArgList &DriverArgs, ArgStringList &CC1Args) const { 764bdd1243dSDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc, 765bdd1243dSDimitry Andric options::OPT_nostdincxx)) 7660b57cec5SDimitry Andric return; 7670b57cec5SDimitry Andric 7680b57cec5SDimitry Andric StringRef Slash = llvm::sys::path::get_separator(); 7690b57cec5SDimitry Andric 7700b57cec5SDimitry Andric switch (GetCXXStdlibType(DriverArgs)) { 771349cc55cSDimitry Andric case ToolChain::CST_Libcxx: { 772349cc55cSDimitry Andric std::string TargetDir = (Base + "include" + Slash + getTripleString() + 773349cc55cSDimitry Andric Slash + "c++" + Slash + "v1") 774349cc55cSDimitry Andric .str(); 775349cc55cSDimitry Andric if (getDriver().getVFS().exists(TargetDir)) 776349cc55cSDimitry Andric addSystemInclude(DriverArgs, CC1Args, TargetDir); 777349cc55cSDimitry Andric addSystemInclude(DriverArgs, CC1Args, 778349cc55cSDimitry Andric Base + SubdirName + Slash + "include" + Slash + "c++" + 779349cc55cSDimitry Andric Slash + "v1"); 7800b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, 7810b57cec5SDimitry Andric Base + "include" + Slash + "c++" + Slash + "v1"); 7820b57cec5SDimitry Andric break; 783349cc55cSDimitry Andric } 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric case ToolChain::CST_Libstdcxx: 786753f127fSDimitry Andric llvm::SmallVector<llvm::SmallString<1024>, 7> CppIncludeBases; 7870b57cec5SDimitry Andric CppIncludeBases.emplace_back(Base); 788349cc55cSDimitry Andric llvm::sys::path::append(CppIncludeBases[0], SubdirName, "include", "c++"); 7890b57cec5SDimitry Andric CppIncludeBases.emplace_back(Base); 790349cc55cSDimitry Andric llvm::sys::path::append(CppIncludeBases[1], SubdirName, "include", "c++", 791349cc55cSDimitry Andric Ver); 7920b57cec5SDimitry Andric CppIncludeBases.emplace_back(Base); 7930b57cec5SDimitry Andric llvm::sys::path::append(CppIncludeBases[2], "include", "c++", Ver); 7940b57cec5SDimitry Andric CppIncludeBases.emplace_back(GccLibDir); 7950b57cec5SDimitry Andric llvm::sys::path::append(CppIncludeBases[3], "include", "c++"); 796753f127fSDimitry Andric CppIncludeBases.emplace_back(GccLibDir); 797753f127fSDimitry Andric llvm::sys::path::append(CppIncludeBases[4], "include", 798753f127fSDimitry Andric "g++-v" + GccVer.Text); 799753f127fSDimitry Andric CppIncludeBases.emplace_back(GccLibDir); 800753f127fSDimitry Andric llvm::sys::path::append(CppIncludeBases[5], "include", 801753f127fSDimitry Andric "g++-v" + GccVer.MajorStr + "." + GccVer.MinorStr); 802753f127fSDimitry Andric CppIncludeBases.emplace_back(GccLibDir); 803753f127fSDimitry Andric llvm::sys::path::append(CppIncludeBases[6], "include", 804753f127fSDimitry Andric "g++-v" + GccVer.MajorStr); 8050b57cec5SDimitry Andric for (auto &CppIncludeBase : CppIncludeBases) { 8060b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, CppIncludeBase); 8070b57cec5SDimitry Andric CppIncludeBase += Slash; 808bdd1243dSDimitry Andric addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + TripleDirName); 8090b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + "backward"); 8100b57cec5SDimitry Andric } 8110b57cec5SDimitry Andric break; 8120b57cec5SDimitry Andric } 8130b57cec5SDimitry Andric } 814349cc55cSDimitry Andric 815349cc55cSDimitry Andric static bool testTriple(const Driver &D, const llvm::Triple &Triple, 816349cc55cSDimitry Andric const ArgList &Args) { 817349cc55cSDimitry Andric // If an explicit sysroot is set, that will be used and we shouldn't try to 818349cc55cSDimitry Andric // detect anything else. 819349cc55cSDimitry Andric std::string SubdirName; 820349cc55cSDimitry Andric if (D.SysRoot.size()) 821349cc55cSDimitry Andric return true; 822bdd1243dSDimitry Andric llvm::Triple LiteralTriple = getLiteralTriple(D, Triple); 823*0fca6ea1SDimitry Andric std::string InstallBase = std::string(llvm::sys::path::parent_path(D.Dir)); 824349cc55cSDimitry Andric if (llvm::ErrorOr<std::string> TargetSubdir = 825bdd1243dSDimitry Andric findClangRelativeSysroot(D, LiteralTriple, Triple, SubdirName)) 826349cc55cSDimitry Andric return true; 8271db9f3b2SDimitry Andric // If the install base itself looks like a mingw sysroot, we'll use that 8281db9f3b2SDimitry Andric // - don't use any potentially unrelated gcc to influence what triple to use. 8291db9f3b2SDimitry Andric if (looksLikeMinGWSysroot(InstallBase)) 8301db9f3b2SDimitry Andric return false; 831bdd1243dSDimitry Andric if (llvm::ErrorOr<std::string> GPPName = findGcc(LiteralTriple, Triple)) 832349cc55cSDimitry Andric return true; 833349cc55cSDimitry Andric // If we neither found a colocated sysroot or a matching gcc executable, 834349cc55cSDimitry Andric // conclude that we can't know if this is the correct spelling of the triple. 835349cc55cSDimitry Andric return false; 836349cc55cSDimitry Andric } 837349cc55cSDimitry Andric 838349cc55cSDimitry Andric static llvm::Triple adjustTriple(const Driver &D, const llvm::Triple &Triple, 839349cc55cSDimitry Andric const ArgList &Args) { 840349cc55cSDimitry Andric // First test if the original triple can find a sysroot with the triple 841349cc55cSDimitry Andric // name. 842349cc55cSDimitry Andric if (testTriple(D, Triple, Args)) 843349cc55cSDimitry Andric return Triple; 844349cc55cSDimitry Andric llvm::SmallVector<llvm::StringRef, 3> Archs; 845349cc55cSDimitry Andric // If not, test a couple other possible arch names that might be what was 846349cc55cSDimitry Andric // intended. 847349cc55cSDimitry Andric if (Triple.getArch() == llvm::Triple::x86) { 848349cc55cSDimitry Andric Archs.emplace_back("i386"); 849349cc55cSDimitry Andric Archs.emplace_back("i586"); 850349cc55cSDimitry Andric Archs.emplace_back("i686"); 851349cc55cSDimitry Andric } else if (Triple.getArch() == llvm::Triple::arm || 852349cc55cSDimitry Andric Triple.getArch() == llvm::Triple::thumb) { 853349cc55cSDimitry Andric Archs.emplace_back("armv7"); 854349cc55cSDimitry Andric } 855349cc55cSDimitry Andric for (auto A : Archs) { 856349cc55cSDimitry Andric llvm::Triple TestTriple(Triple); 857349cc55cSDimitry Andric TestTriple.setArchName(A); 858349cc55cSDimitry Andric if (testTriple(D, TestTriple, Args)) 859349cc55cSDimitry Andric return TestTriple; 860349cc55cSDimitry Andric } 861349cc55cSDimitry Andric // If none was found, just proceed with the original value. 862349cc55cSDimitry Andric return Triple; 863349cc55cSDimitry Andric } 864349cc55cSDimitry Andric 865349cc55cSDimitry Andric void toolchains::MinGW::fixTripleArch(const Driver &D, llvm::Triple &Triple, 866349cc55cSDimitry Andric const ArgList &Args) { 867349cc55cSDimitry Andric if (Triple.getArch() == llvm::Triple::x86 || 868349cc55cSDimitry Andric Triple.getArch() == llvm::Triple::arm || 869349cc55cSDimitry Andric Triple.getArch() == llvm::Triple::thumb) 870349cc55cSDimitry Andric Triple = adjustTriple(D, Triple, Args); 871349cc55cSDimitry Andric } 872