1*e5dd7070Spatrick //===--- MinGW.cpp - MinGWToolChain Implementation ------------------------===// 2*e5dd7070Spatrick // 3*e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information. 5*e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*e5dd7070Spatrick // 7*e5dd7070Spatrick //===----------------------------------------------------------------------===// 8*e5dd7070Spatrick 9*e5dd7070Spatrick #include "MinGW.h" 10*e5dd7070Spatrick #include "InputInfo.h" 11*e5dd7070Spatrick #include "CommonArgs.h" 12*e5dd7070Spatrick #include "clang/Config/config.h" 13*e5dd7070Spatrick #include "clang/Driver/Compilation.h" 14*e5dd7070Spatrick #include "clang/Driver/Driver.h" 15*e5dd7070Spatrick #include "clang/Driver/DriverDiagnostic.h" 16*e5dd7070Spatrick #include "clang/Driver/Options.h" 17*e5dd7070Spatrick #include "clang/Driver/SanitizerArgs.h" 18*e5dd7070Spatrick #include "llvm/Option/ArgList.h" 19*e5dd7070Spatrick #include "llvm/Support/FileSystem.h" 20*e5dd7070Spatrick #include "llvm/Support/Path.h" 21*e5dd7070Spatrick #include <system_error> 22*e5dd7070Spatrick 23*e5dd7070Spatrick using namespace clang::diag; 24*e5dd7070Spatrick using namespace clang::driver; 25*e5dd7070Spatrick using namespace clang; 26*e5dd7070Spatrick using namespace llvm::opt; 27*e5dd7070Spatrick 28*e5dd7070Spatrick /// MinGW Tools 29*e5dd7070Spatrick void tools::MinGW::Assembler::ConstructJob(Compilation &C, const JobAction &JA, 30*e5dd7070Spatrick const InputInfo &Output, 31*e5dd7070Spatrick const InputInfoList &Inputs, 32*e5dd7070Spatrick const ArgList &Args, 33*e5dd7070Spatrick const char *LinkingOutput) const { 34*e5dd7070Spatrick claimNoWarnArgs(Args); 35*e5dd7070Spatrick ArgStringList CmdArgs; 36*e5dd7070Spatrick 37*e5dd7070Spatrick if (getToolChain().getArch() == llvm::Triple::x86) { 38*e5dd7070Spatrick CmdArgs.push_back("--32"); 39*e5dd7070Spatrick } else if (getToolChain().getArch() == llvm::Triple::x86_64) { 40*e5dd7070Spatrick CmdArgs.push_back("--64"); 41*e5dd7070Spatrick } 42*e5dd7070Spatrick 43*e5dd7070Spatrick Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); 44*e5dd7070Spatrick 45*e5dd7070Spatrick CmdArgs.push_back("-o"); 46*e5dd7070Spatrick CmdArgs.push_back(Output.getFilename()); 47*e5dd7070Spatrick 48*e5dd7070Spatrick for (const auto &II : Inputs) 49*e5dd7070Spatrick CmdArgs.push_back(II.getFilename()); 50*e5dd7070Spatrick 51*e5dd7070Spatrick const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); 52*e5dd7070Spatrick C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); 53*e5dd7070Spatrick 54*e5dd7070Spatrick if (Args.hasArg(options::OPT_gsplit_dwarf)) 55*e5dd7070Spatrick SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, 56*e5dd7070Spatrick SplitDebugName(Args, Inputs[0], Output)); 57*e5dd7070Spatrick } 58*e5dd7070Spatrick 59*e5dd7070Spatrick void tools::MinGW::Linker::AddLibGCC(const ArgList &Args, 60*e5dd7070Spatrick ArgStringList &CmdArgs) const { 61*e5dd7070Spatrick if (Args.hasArg(options::OPT_mthreads)) 62*e5dd7070Spatrick CmdArgs.push_back("-lmingwthrd"); 63*e5dd7070Spatrick CmdArgs.push_back("-lmingw32"); 64*e5dd7070Spatrick 65*e5dd7070Spatrick // Make use of compiler-rt if --rtlib option is used 66*e5dd7070Spatrick ToolChain::RuntimeLibType RLT = getToolChain().GetRuntimeLibType(Args); 67*e5dd7070Spatrick if (RLT == ToolChain::RLT_Libgcc) { 68*e5dd7070Spatrick bool Static = Args.hasArg(options::OPT_static_libgcc) || 69*e5dd7070Spatrick Args.hasArg(options::OPT_static); 70*e5dd7070Spatrick bool Shared = Args.hasArg(options::OPT_shared); 71*e5dd7070Spatrick bool CXX = getToolChain().getDriver().CCCIsCXX(); 72*e5dd7070Spatrick 73*e5dd7070Spatrick if (Static || (!CXX && !Shared)) { 74*e5dd7070Spatrick CmdArgs.push_back("-lgcc"); 75*e5dd7070Spatrick CmdArgs.push_back("-lgcc_eh"); 76*e5dd7070Spatrick } else { 77*e5dd7070Spatrick CmdArgs.push_back("-lgcc_s"); 78*e5dd7070Spatrick CmdArgs.push_back("-lgcc"); 79*e5dd7070Spatrick } 80*e5dd7070Spatrick } else { 81*e5dd7070Spatrick AddRunTimeLibs(getToolChain(), getToolChain().getDriver(), CmdArgs, Args); 82*e5dd7070Spatrick } 83*e5dd7070Spatrick 84*e5dd7070Spatrick CmdArgs.push_back("-lmoldname"); 85*e5dd7070Spatrick CmdArgs.push_back("-lmingwex"); 86*e5dd7070Spatrick for (auto Lib : Args.getAllArgValues(options::OPT_l)) 87*e5dd7070Spatrick if (StringRef(Lib).startswith("msvcr") || StringRef(Lib).startswith("ucrt")) 88*e5dd7070Spatrick return; 89*e5dd7070Spatrick CmdArgs.push_back("-lmsvcrt"); 90*e5dd7070Spatrick } 91*e5dd7070Spatrick 92*e5dd7070Spatrick void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, 93*e5dd7070Spatrick const InputInfo &Output, 94*e5dd7070Spatrick const InputInfoList &Inputs, 95*e5dd7070Spatrick const ArgList &Args, 96*e5dd7070Spatrick const char *LinkingOutput) const { 97*e5dd7070Spatrick const ToolChain &TC = getToolChain(); 98*e5dd7070Spatrick const Driver &D = TC.getDriver(); 99*e5dd7070Spatrick const SanitizerArgs &Sanitize = TC.getSanitizerArgs(); 100*e5dd7070Spatrick 101*e5dd7070Spatrick ArgStringList CmdArgs; 102*e5dd7070Spatrick 103*e5dd7070Spatrick // Silence warning for "clang -g foo.o -o foo" 104*e5dd7070Spatrick Args.ClaimAllArgs(options::OPT_g_Group); 105*e5dd7070Spatrick // and "clang -emit-llvm foo.o -o foo" 106*e5dd7070Spatrick Args.ClaimAllArgs(options::OPT_emit_llvm); 107*e5dd7070Spatrick // and for "clang -w foo.o -o foo". Other warning options are already 108*e5dd7070Spatrick // handled somewhere else. 109*e5dd7070Spatrick Args.ClaimAllArgs(options::OPT_w); 110*e5dd7070Spatrick 111*e5dd7070Spatrick if (!D.SysRoot.empty()) 112*e5dd7070Spatrick CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); 113*e5dd7070Spatrick 114*e5dd7070Spatrick if (Args.hasArg(options::OPT_s)) 115*e5dd7070Spatrick CmdArgs.push_back("-s"); 116*e5dd7070Spatrick 117*e5dd7070Spatrick CmdArgs.push_back("-m"); 118*e5dd7070Spatrick switch (TC.getArch()) { 119*e5dd7070Spatrick case llvm::Triple::x86: 120*e5dd7070Spatrick CmdArgs.push_back("i386pe"); 121*e5dd7070Spatrick break; 122*e5dd7070Spatrick case llvm::Triple::x86_64: 123*e5dd7070Spatrick CmdArgs.push_back("i386pep"); 124*e5dd7070Spatrick break; 125*e5dd7070Spatrick case llvm::Triple::arm: 126*e5dd7070Spatrick case llvm::Triple::thumb: 127*e5dd7070Spatrick // FIXME: this is incorrect for WinCE 128*e5dd7070Spatrick CmdArgs.push_back("thumb2pe"); 129*e5dd7070Spatrick break; 130*e5dd7070Spatrick case llvm::Triple::aarch64: 131*e5dd7070Spatrick CmdArgs.push_back("arm64pe"); 132*e5dd7070Spatrick break; 133*e5dd7070Spatrick default: 134*e5dd7070Spatrick llvm_unreachable("Unsupported target architecture."); 135*e5dd7070Spatrick } 136*e5dd7070Spatrick 137*e5dd7070Spatrick if (Args.hasArg(options::OPT_mwindows)) { 138*e5dd7070Spatrick CmdArgs.push_back("--subsystem"); 139*e5dd7070Spatrick CmdArgs.push_back("windows"); 140*e5dd7070Spatrick } else if (Args.hasArg(options::OPT_mconsole)) { 141*e5dd7070Spatrick CmdArgs.push_back("--subsystem"); 142*e5dd7070Spatrick CmdArgs.push_back("console"); 143*e5dd7070Spatrick } 144*e5dd7070Spatrick 145*e5dd7070Spatrick if (Args.hasArg(options::OPT_mdll)) 146*e5dd7070Spatrick CmdArgs.push_back("--dll"); 147*e5dd7070Spatrick else if (Args.hasArg(options::OPT_shared)) 148*e5dd7070Spatrick CmdArgs.push_back("--shared"); 149*e5dd7070Spatrick if (Args.hasArg(options::OPT_static)) 150*e5dd7070Spatrick CmdArgs.push_back("-Bstatic"); 151*e5dd7070Spatrick else 152*e5dd7070Spatrick CmdArgs.push_back("-Bdynamic"); 153*e5dd7070Spatrick if (Args.hasArg(options::OPT_mdll) || Args.hasArg(options::OPT_shared)) { 154*e5dd7070Spatrick CmdArgs.push_back("-e"); 155*e5dd7070Spatrick if (TC.getArch() == llvm::Triple::x86) 156*e5dd7070Spatrick CmdArgs.push_back("_DllMainCRTStartup@12"); 157*e5dd7070Spatrick else 158*e5dd7070Spatrick CmdArgs.push_back("DllMainCRTStartup"); 159*e5dd7070Spatrick CmdArgs.push_back("--enable-auto-image-base"); 160*e5dd7070Spatrick } 161*e5dd7070Spatrick 162*e5dd7070Spatrick CmdArgs.push_back("-o"); 163*e5dd7070Spatrick const char *OutputFile = Output.getFilename(); 164*e5dd7070Spatrick // GCC implicitly adds an .exe extension if it is given an output file name 165*e5dd7070Spatrick // that lacks an extension. However, GCC only does this when actually 166*e5dd7070Spatrick // running on windows, not when operating as a cross compiler. As some users 167*e5dd7070Spatrick // have come to rely on this behaviour, try to replicate it. 168*e5dd7070Spatrick #ifdef _WIN32 169*e5dd7070Spatrick if (!llvm::sys::path::has_extension(OutputFile)) 170*e5dd7070Spatrick CmdArgs.push_back(Args.MakeArgString(Twine(OutputFile) + ".exe")); 171*e5dd7070Spatrick else 172*e5dd7070Spatrick CmdArgs.push_back(OutputFile); 173*e5dd7070Spatrick #else 174*e5dd7070Spatrick CmdArgs.push_back(OutputFile); 175*e5dd7070Spatrick #endif 176*e5dd7070Spatrick 177*e5dd7070Spatrick Args.AddAllArgs(CmdArgs, options::OPT_e); 178*e5dd7070Spatrick // FIXME: add -N, -n flags 179*e5dd7070Spatrick Args.AddLastArg(CmdArgs, options::OPT_r); 180*e5dd7070Spatrick Args.AddLastArg(CmdArgs, options::OPT_s); 181*e5dd7070Spatrick Args.AddLastArg(CmdArgs, options::OPT_t); 182*e5dd7070Spatrick Args.AddAllArgs(CmdArgs, options::OPT_u_Group); 183*e5dd7070Spatrick Args.AddLastArg(CmdArgs, options::OPT_Z_Flag); 184*e5dd7070Spatrick 185*e5dd7070Spatrick if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { 186*e5dd7070Spatrick if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_mdll)) { 187*e5dd7070Spatrick CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("dllcrt2.o"))); 188*e5dd7070Spatrick } else { 189*e5dd7070Spatrick if (Args.hasArg(options::OPT_municode)) 190*e5dd7070Spatrick CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2u.o"))); 191*e5dd7070Spatrick else 192*e5dd7070Spatrick CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2.o"))); 193*e5dd7070Spatrick } 194*e5dd7070Spatrick if (Args.hasArg(options::OPT_pg)) 195*e5dd7070Spatrick CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("gcrt2.o"))); 196*e5dd7070Spatrick CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o"))); 197*e5dd7070Spatrick } 198*e5dd7070Spatrick 199*e5dd7070Spatrick Args.AddAllArgs(CmdArgs, options::OPT_L); 200*e5dd7070Spatrick TC.AddFilePathLibArgs(Args, CmdArgs); 201*e5dd7070Spatrick AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); 202*e5dd7070Spatrick 203*e5dd7070Spatrick // TODO: Add profile stuff here 204*e5dd7070Spatrick 205*e5dd7070Spatrick if (TC.ShouldLinkCXXStdlib(Args)) { 206*e5dd7070Spatrick bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && 207*e5dd7070Spatrick !Args.hasArg(options::OPT_static); 208*e5dd7070Spatrick if (OnlyLibstdcxxStatic) 209*e5dd7070Spatrick CmdArgs.push_back("-Bstatic"); 210*e5dd7070Spatrick TC.AddCXXStdlibLibArgs(Args, CmdArgs); 211*e5dd7070Spatrick if (OnlyLibstdcxxStatic) 212*e5dd7070Spatrick CmdArgs.push_back("-Bdynamic"); 213*e5dd7070Spatrick } 214*e5dd7070Spatrick 215*e5dd7070Spatrick bool HasWindowsApp = false; 216*e5dd7070Spatrick for (auto Lib : Args.getAllArgValues(options::OPT_l)) { 217*e5dd7070Spatrick if (Lib == "windowsapp") { 218*e5dd7070Spatrick HasWindowsApp = true; 219*e5dd7070Spatrick break; 220*e5dd7070Spatrick } 221*e5dd7070Spatrick } 222*e5dd7070Spatrick 223*e5dd7070Spatrick if (!Args.hasArg(options::OPT_nostdlib)) { 224*e5dd7070Spatrick if (!Args.hasArg(options::OPT_nodefaultlibs)) { 225*e5dd7070Spatrick if (Args.hasArg(options::OPT_static)) 226*e5dd7070Spatrick CmdArgs.push_back("--start-group"); 227*e5dd7070Spatrick 228*e5dd7070Spatrick if (Args.hasArg(options::OPT_fstack_protector) || 229*e5dd7070Spatrick Args.hasArg(options::OPT_fstack_protector_strong) || 230*e5dd7070Spatrick Args.hasArg(options::OPT_fstack_protector_all)) { 231*e5dd7070Spatrick CmdArgs.push_back("-lssp_nonshared"); 232*e5dd7070Spatrick CmdArgs.push_back("-lssp"); 233*e5dd7070Spatrick } 234*e5dd7070Spatrick 235*e5dd7070Spatrick if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, 236*e5dd7070Spatrick options::OPT_fno_openmp, false)) { 237*e5dd7070Spatrick switch (TC.getDriver().getOpenMPRuntime(Args)) { 238*e5dd7070Spatrick case Driver::OMPRT_OMP: 239*e5dd7070Spatrick CmdArgs.push_back("-lomp"); 240*e5dd7070Spatrick break; 241*e5dd7070Spatrick case Driver::OMPRT_IOMP5: 242*e5dd7070Spatrick CmdArgs.push_back("-liomp5md"); 243*e5dd7070Spatrick break; 244*e5dd7070Spatrick case Driver::OMPRT_GOMP: 245*e5dd7070Spatrick CmdArgs.push_back("-lgomp"); 246*e5dd7070Spatrick break; 247*e5dd7070Spatrick case Driver::OMPRT_Unknown: 248*e5dd7070Spatrick // Already diagnosed. 249*e5dd7070Spatrick break; 250*e5dd7070Spatrick } 251*e5dd7070Spatrick } 252*e5dd7070Spatrick 253*e5dd7070Spatrick AddLibGCC(Args, CmdArgs); 254*e5dd7070Spatrick 255*e5dd7070Spatrick if (Args.hasArg(options::OPT_pg)) 256*e5dd7070Spatrick CmdArgs.push_back("-lgmon"); 257*e5dd7070Spatrick 258*e5dd7070Spatrick if (Args.hasArg(options::OPT_pthread)) 259*e5dd7070Spatrick CmdArgs.push_back("-lpthread"); 260*e5dd7070Spatrick 261*e5dd7070Spatrick if (Sanitize.needsAsanRt()) { 262*e5dd7070Spatrick // MinGW always links against a shared MSVCRT. 263*e5dd7070Spatrick CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dynamic", 264*e5dd7070Spatrick ToolChain::FT_Shared)); 265*e5dd7070Spatrick CmdArgs.push_back( 266*e5dd7070Spatrick TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); 267*e5dd7070Spatrick CmdArgs.push_back("--require-defined"); 268*e5dd7070Spatrick CmdArgs.push_back(TC.getArch() == llvm::Triple::x86 269*e5dd7070Spatrick ? "___asan_seh_interceptor" 270*e5dd7070Spatrick : "__asan_seh_interceptor"); 271*e5dd7070Spatrick // Make sure the linker consider all object files from the dynamic 272*e5dd7070Spatrick // runtime thunk. 273*e5dd7070Spatrick CmdArgs.push_back("--whole-archive"); 274*e5dd7070Spatrick CmdArgs.push_back( 275*e5dd7070Spatrick TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); 276*e5dd7070Spatrick CmdArgs.push_back("--no-whole-archive"); 277*e5dd7070Spatrick } 278*e5dd7070Spatrick 279*e5dd7070Spatrick TC.addProfileRTLibs(Args, CmdArgs); 280*e5dd7070Spatrick 281*e5dd7070Spatrick if (!HasWindowsApp) { 282*e5dd7070Spatrick // Add system libraries. If linking to libwindowsapp.a, that import 283*e5dd7070Spatrick // library replaces all these and we shouldn't accidentally try to 284*e5dd7070Spatrick // link to the normal desktop mode dlls. 285*e5dd7070Spatrick if (Args.hasArg(options::OPT_mwindows)) { 286*e5dd7070Spatrick CmdArgs.push_back("-lgdi32"); 287*e5dd7070Spatrick CmdArgs.push_back("-lcomdlg32"); 288*e5dd7070Spatrick } 289*e5dd7070Spatrick CmdArgs.push_back("-ladvapi32"); 290*e5dd7070Spatrick CmdArgs.push_back("-lshell32"); 291*e5dd7070Spatrick CmdArgs.push_back("-luser32"); 292*e5dd7070Spatrick CmdArgs.push_back("-lkernel32"); 293*e5dd7070Spatrick } 294*e5dd7070Spatrick 295*e5dd7070Spatrick if (Args.hasArg(options::OPT_static)) 296*e5dd7070Spatrick CmdArgs.push_back("--end-group"); 297*e5dd7070Spatrick else 298*e5dd7070Spatrick AddLibGCC(Args, CmdArgs); 299*e5dd7070Spatrick } 300*e5dd7070Spatrick 301*e5dd7070Spatrick if (!Args.hasArg(options::OPT_nostartfiles)) { 302*e5dd7070Spatrick // Add crtfastmath.o if available and fast math is enabled. 303*e5dd7070Spatrick TC.AddFastMathRuntimeIfAvailable(Args, CmdArgs); 304*e5dd7070Spatrick 305*e5dd7070Spatrick CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o"))); 306*e5dd7070Spatrick } 307*e5dd7070Spatrick } 308*e5dd7070Spatrick const char *Exec = Args.MakeArgString(TC.GetLinkerPath()); 309*e5dd7070Spatrick C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); 310*e5dd7070Spatrick } 311*e5dd7070Spatrick 312*e5dd7070Spatrick // Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple. 313*e5dd7070Spatrick static bool findGccVersion(StringRef LibDir, std::string &GccLibDir, 314*e5dd7070Spatrick std::string &Ver) { 315*e5dd7070Spatrick auto Version = toolchains::Generic_GCC::GCCVersion::Parse("0.0.0"); 316*e5dd7070Spatrick std::error_code EC; 317*e5dd7070Spatrick for (llvm::sys::fs::directory_iterator LI(LibDir, EC), LE; !EC && LI != LE; 318*e5dd7070Spatrick LI = LI.increment(EC)) { 319*e5dd7070Spatrick StringRef VersionText = llvm::sys::path::filename(LI->path()); 320*e5dd7070Spatrick auto CandidateVersion = 321*e5dd7070Spatrick toolchains::Generic_GCC::GCCVersion::Parse(VersionText); 322*e5dd7070Spatrick if (CandidateVersion.Major == -1) 323*e5dd7070Spatrick continue; 324*e5dd7070Spatrick if (CandidateVersion <= Version) 325*e5dd7070Spatrick continue; 326*e5dd7070Spatrick Ver = VersionText; 327*e5dd7070Spatrick GccLibDir = LI->path(); 328*e5dd7070Spatrick } 329*e5dd7070Spatrick return Ver.size(); 330*e5dd7070Spatrick } 331*e5dd7070Spatrick 332*e5dd7070Spatrick void toolchains::MinGW::findGccLibDir() { 333*e5dd7070Spatrick llvm::SmallVector<llvm::SmallString<32>, 2> Archs; 334*e5dd7070Spatrick Archs.emplace_back(getTriple().getArchName()); 335*e5dd7070Spatrick Archs[0] += "-w64-mingw32"; 336*e5dd7070Spatrick Archs.emplace_back("mingw32"); 337*e5dd7070Spatrick if (Arch.empty()) 338*e5dd7070Spatrick Arch = Archs[0].str(); 339*e5dd7070Spatrick // lib: Arch Linux, Ubuntu, Windows 340*e5dd7070Spatrick // lib64: openSUSE Linux 341*e5dd7070Spatrick for (StringRef CandidateLib : {"lib", "lib64"}) { 342*e5dd7070Spatrick for (StringRef CandidateArch : Archs) { 343*e5dd7070Spatrick llvm::SmallString<1024> LibDir(Base); 344*e5dd7070Spatrick llvm::sys::path::append(LibDir, CandidateLib, "gcc", CandidateArch); 345*e5dd7070Spatrick if (findGccVersion(LibDir, GccLibDir, Ver)) { 346*e5dd7070Spatrick Arch = CandidateArch; 347*e5dd7070Spatrick return; 348*e5dd7070Spatrick } 349*e5dd7070Spatrick } 350*e5dd7070Spatrick } 351*e5dd7070Spatrick } 352*e5dd7070Spatrick 353*e5dd7070Spatrick llvm::ErrorOr<std::string> toolchains::MinGW::findGcc() { 354*e5dd7070Spatrick llvm::SmallVector<llvm::SmallString<32>, 2> Gccs; 355*e5dd7070Spatrick Gccs.emplace_back(getTriple().getArchName()); 356*e5dd7070Spatrick Gccs[0] += "-w64-mingw32-gcc"; 357*e5dd7070Spatrick Gccs.emplace_back("mingw32-gcc"); 358*e5dd7070Spatrick // Please do not add "gcc" here 359*e5dd7070Spatrick for (StringRef CandidateGcc : Gccs) 360*e5dd7070Spatrick if (llvm::ErrorOr<std::string> GPPName = llvm::sys::findProgramByName(CandidateGcc)) 361*e5dd7070Spatrick return GPPName; 362*e5dd7070Spatrick return make_error_code(std::errc::no_such_file_or_directory); 363*e5dd7070Spatrick } 364*e5dd7070Spatrick 365*e5dd7070Spatrick llvm::ErrorOr<std::string> toolchains::MinGW::findClangRelativeSysroot() { 366*e5dd7070Spatrick llvm::SmallVector<llvm::SmallString<32>, 2> Subdirs; 367*e5dd7070Spatrick Subdirs.emplace_back(getTriple().str()); 368*e5dd7070Spatrick Subdirs.emplace_back(getTriple().getArchName()); 369*e5dd7070Spatrick Subdirs[1] += "-w64-mingw32"; 370*e5dd7070Spatrick StringRef ClangRoot = 371*e5dd7070Spatrick llvm::sys::path::parent_path(getDriver().getInstalledDir()); 372*e5dd7070Spatrick StringRef Sep = llvm::sys::path::get_separator(); 373*e5dd7070Spatrick for (StringRef CandidateSubdir : Subdirs) { 374*e5dd7070Spatrick if (llvm::sys::fs::is_directory(ClangRoot + Sep + CandidateSubdir)) { 375*e5dd7070Spatrick Arch = CandidateSubdir; 376*e5dd7070Spatrick return (ClangRoot + Sep + CandidateSubdir).str(); 377*e5dd7070Spatrick } 378*e5dd7070Spatrick } 379*e5dd7070Spatrick return make_error_code(std::errc::no_such_file_or_directory); 380*e5dd7070Spatrick } 381*e5dd7070Spatrick 382*e5dd7070Spatrick toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, 383*e5dd7070Spatrick const ArgList &Args) 384*e5dd7070Spatrick : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args) { 385*e5dd7070Spatrick getProgramPaths().push_back(getDriver().getInstalledDir()); 386*e5dd7070Spatrick 387*e5dd7070Spatrick if (getDriver().SysRoot.size()) 388*e5dd7070Spatrick Base = getDriver().SysRoot; 389*e5dd7070Spatrick // Look for <clang-bin>/../<triplet>; if found, use <clang-bin>/.. as the 390*e5dd7070Spatrick // base as it could still be a base for a gcc setup with libgcc. 391*e5dd7070Spatrick else if (llvm::ErrorOr<std::string> TargetSubdir = findClangRelativeSysroot()) 392*e5dd7070Spatrick Base = llvm::sys::path::parent_path(TargetSubdir.get()); 393*e5dd7070Spatrick else if (llvm::ErrorOr<std::string> GPPName = findGcc()) 394*e5dd7070Spatrick Base = llvm::sys::path::parent_path( 395*e5dd7070Spatrick llvm::sys::path::parent_path(GPPName.get())); 396*e5dd7070Spatrick else 397*e5dd7070Spatrick Base = llvm::sys::path::parent_path(getDriver().getInstalledDir()); 398*e5dd7070Spatrick 399*e5dd7070Spatrick Base += llvm::sys::path::get_separator(); 400*e5dd7070Spatrick findGccLibDir(); 401*e5dd7070Spatrick // GccLibDir must precede Base/lib so that the 402*e5dd7070Spatrick // correct crtbegin.o ,cetend.o would be found. 403*e5dd7070Spatrick getFilePaths().push_back(GccLibDir); 404*e5dd7070Spatrick getFilePaths().push_back( 405*e5dd7070Spatrick (Base + Arch + llvm::sys::path::get_separator() + "lib").str()); 406*e5dd7070Spatrick getFilePaths().push_back(Base + "lib"); 407*e5dd7070Spatrick // openSUSE 408*e5dd7070Spatrick getFilePaths().push_back(Base + Arch + "/sys-root/mingw/lib"); 409*e5dd7070Spatrick 410*e5dd7070Spatrick NativeLLVMSupport = 411*e5dd7070Spatrick Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER) 412*e5dd7070Spatrick .equals_lower("lld"); 413*e5dd7070Spatrick } 414*e5dd7070Spatrick 415*e5dd7070Spatrick bool toolchains::MinGW::IsIntegratedAssemblerDefault() const { return true; } 416*e5dd7070Spatrick 417*e5dd7070Spatrick Tool *toolchains::MinGW::getTool(Action::ActionClass AC) const { 418*e5dd7070Spatrick switch (AC) { 419*e5dd7070Spatrick case Action::PreprocessJobClass: 420*e5dd7070Spatrick if (!Preprocessor) 421*e5dd7070Spatrick Preprocessor.reset(new tools::gcc::Preprocessor(*this)); 422*e5dd7070Spatrick return Preprocessor.get(); 423*e5dd7070Spatrick case Action::CompileJobClass: 424*e5dd7070Spatrick if (!Compiler) 425*e5dd7070Spatrick Compiler.reset(new tools::gcc::Compiler(*this)); 426*e5dd7070Spatrick return Compiler.get(); 427*e5dd7070Spatrick default: 428*e5dd7070Spatrick return ToolChain::getTool(AC); 429*e5dd7070Spatrick } 430*e5dd7070Spatrick } 431*e5dd7070Spatrick 432*e5dd7070Spatrick Tool *toolchains::MinGW::buildAssembler() const { 433*e5dd7070Spatrick return new tools::MinGW::Assembler(*this); 434*e5dd7070Spatrick } 435*e5dd7070Spatrick 436*e5dd7070Spatrick Tool *toolchains::MinGW::buildLinker() const { 437*e5dd7070Spatrick return new tools::MinGW::Linker(*this); 438*e5dd7070Spatrick } 439*e5dd7070Spatrick 440*e5dd7070Spatrick bool toolchains::MinGW::HasNativeLLVMSupport() const { 441*e5dd7070Spatrick return NativeLLVMSupport; 442*e5dd7070Spatrick } 443*e5dd7070Spatrick 444*e5dd7070Spatrick bool toolchains::MinGW::IsUnwindTablesDefault(const ArgList &Args) const { 445*e5dd7070Spatrick Arg *ExceptionArg = Args.getLastArg(options::OPT_fsjlj_exceptions, 446*e5dd7070Spatrick options::OPT_fseh_exceptions, 447*e5dd7070Spatrick options::OPT_fdwarf_exceptions); 448*e5dd7070Spatrick if (ExceptionArg && 449*e5dd7070Spatrick ExceptionArg->getOption().matches(options::OPT_fseh_exceptions)) 450*e5dd7070Spatrick return true; 451*e5dd7070Spatrick return getArch() == llvm::Triple::x86_64 || 452*e5dd7070Spatrick getArch() == llvm::Triple::aarch64; 453*e5dd7070Spatrick } 454*e5dd7070Spatrick 455*e5dd7070Spatrick bool toolchains::MinGW::isPICDefault() const { 456*e5dd7070Spatrick return getArch() == llvm::Triple::x86_64; 457*e5dd7070Spatrick } 458*e5dd7070Spatrick 459*e5dd7070Spatrick bool toolchains::MinGW::isPIEDefault() const { return false; } 460*e5dd7070Spatrick 461*e5dd7070Spatrick bool toolchains::MinGW::isPICDefaultForced() const { 462*e5dd7070Spatrick return getArch() == llvm::Triple::x86_64; 463*e5dd7070Spatrick } 464*e5dd7070Spatrick 465*e5dd7070Spatrick llvm::ExceptionHandling 466*e5dd7070Spatrick toolchains::MinGW::GetExceptionModel(const ArgList &Args) const { 467*e5dd7070Spatrick if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::aarch64) 468*e5dd7070Spatrick return llvm::ExceptionHandling::WinEH; 469*e5dd7070Spatrick return llvm::ExceptionHandling::DwarfCFI; 470*e5dd7070Spatrick } 471*e5dd7070Spatrick 472*e5dd7070Spatrick SanitizerMask toolchains::MinGW::getSupportedSanitizers() const { 473*e5dd7070Spatrick SanitizerMask Res = ToolChain::getSupportedSanitizers(); 474*e5dd7070Spatrick Res |= SanitizerKind::Address; 475*e5dd7070Spatrick Res |= SanitizerKind::PointerCompare; 476*e5dd7070Spatrick Res |= SanitizerKind::PointerSubtract; 477*e5dd7070Spatrick return Res; 478*e5dd7070Spatrick } 479*e5dd7070Spatrick 480*e5dd7070Spatrick void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs, 481*e5dd7070Spatrick ArgStringList &CC1Args) const { 482*e5dd7070Spatrick CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args); 483*e5dd7070Spatrick } 484*e5dd7070Spatrick 485*e5dd7070Spatrick void toolchains::MinGW::printVerboseInfo(raw_ostream &OS) const { 486*e5dd7070Spatrick CudaInstallation.print(OS); 487*e5dd7070Spatrick } 488*e5dd7070Spatrick 489*e5dd7070Spatrick // Include directories for various hosts: 490*e5dd7070Spatrick 491*e5dd7070Spatrick // Windows, mingw.org 492*e5dd7070Spatrick // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++ 493*e5dd7070Spatrick // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\mingw32 494*e5dd7070Spatrick // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\backward 495*e5dd7070Spatrick // c:\mingw\include 496*e5dd7070Spatrick // c:\mingw\mingw32\include 497*e5dd7070Spatrick 498*e5dd7070Spatrick // Windows, mingw-w64 mingw-builds 499*e5dd7070Spatrick // c:\mingw32\i686-w64-mingw32\include 500*e5dd7070Spatrick // c:\mingw32\i686-w64-mingw32\include\c++ 501*e5dd7070Spatrick // c:\mingw32\i686-w64-mingw32\include\c++\i686-w64-mingw32 502*e5dd7070Spatrick // c:\mingw32\i686-w64-mingw32\include\c++\backward 503*e5dd7070Spatrick 504*e5dd7070Spatrick // Windows, mingw-w64 msys2 505*e5dd7070Spatrick // c:\msys64\mingw32\include 506*e5dd7070Spatrick // c:\msys64\mingw32\i686-w64-mingw32\include 507*e5dd7070Spatrick // c:\msys64\mingw32\include\c++\4.9.2 508*e5dd7070Spatrick // c:\msys64\mingw32\include\c++\4.9.2\i686-w64-mingw32 509*e5dd7070Spatrick // c:\msys64\mingw32\include\c++\4.9.2\backward 510*e5dd7070Spatrick 511*e5dd7070Spatrick // openSUSE 512*e5dd7070Spatrick // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++ 513*e5dd7070Spatrick // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/x86_64-w64-mingw32 514*e5dd7070Spatrick // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/backward 515*e5dd7070Spatrick // /usr/x86_64-w64-mingw32/sys-root/mingw/include 516*e5dd7070Spatrick 517*e5dd7070Spatrick // Arch Linux 518*e5dd7070Spatrick // /usr/i686-w64-mingw32/include/c++/5.1.0 519*e5dd7070Spatrick // /usr/i686-w64-mingw32/include/c++/5.1.0/i686-w64-mingw32 520*e5dd7070Spatrick // /usr/i686-w64-mingw32/include/c++/5.1.0/backward 521*e5dd7070Spatrick // /usr/i686-w64-mingw32/include 522*e5dd7070Spatrick 523*e5dd7070Spatrick // Ubuntu 524*e5dd7070Spatrick // /usr/include/c++/4.8 525*e5dd7070Spatrick // /usr/include/c++/4.8/x86_64-w64-mingw32 526*e5dd7070Spatrick // /usr/include/c++/4.8/backward 527*e5dd7070Spatrick // /usr/x86_64-w64-mingw32/include 528*e5dd7070Spatrick 529*e5dd7070Spatrick void toolchains::MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 530*e5dd7070Spatrick ArgStringList &CC1Args) const { 531*e5dd7070Spatrick if (DriverArgs.hasArg(options::OPT_nostdinc)) 532*e5dd7070Spatrick return; 533*e5dd7070Spatrick 534*e5dd7070Spatrick if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 535*e5dd7070Spatrick SmallString<1024> P(getDriver().ResourceDir); 536*e5dd7070Spatrick llvm::sys::path::append(P, "include"); 537*e5dd7070Spatrick addSystemInclude(DriverArgs, CC1Args, P.str()); 538*e5dd7070Spatrick } 539*e5dd7070Spatrick 540*e5dd7070Spatrick if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 541*e5dd7070Spatrick return; 542*e5dd7070Spatrick 543*e5dd7070Spatrick if (GetRuntimeLibType(DriverArgs) == ToolChain::RLT_Libgcc) { 544*e5dd7070Spatrick // openSUSE 545*e5dd7070Spatrick addSystemInclude(DriverArgs, CC1Args, 546*e5dd7070Spatrick Base + Arch + "/sys-root/mingw/include"); 547*e5dd7070Spatrick } 548*e5dd7070Spatrick 549*e5dd7070Spatrick addSystemInclude(DriverArgs, CC1Args, 550*e5dd7070Spatrick Base + Arch + llvm::sys::path::get_separator() + "include"); 551*e5dd7070Spatrick addSystemInclude(DriverArgs, CC1Args, Base + "include"); 552*e5dd7070Spatrick } 553*e5dd7070Spatrick 554*e5dd7070Spatrick void toolchains::MinGW::AddClangCXXStdlibIncludeArgs( 555*e5dd7070Spatrick const ArgList &DriverArgs, ArgStringList &CC1Args) const { 556*e5dd7070Spatrick if (DriverArgs.hasArg(options::OPT_nostdlibinc) || 557*e5dd7070Spatrick DriverArgs.hasArg(options::OPT_nostdincxx)) 558*e5dd7070Spatrick return; 559*e5dd7070Spatrick 560*e5dd7070Spatrick StringRef Slash = llvm::sys::path::get_separator(); 561*e5dd7070Spatrick 562*e5dd7070Spatrick switch (GetCXXStdlibType(DriverArgs)) { 563*e5dd7070Spatrick case ToolChain::CST_Libcxx: 564*e5dd7070Spatrick addSystemInclude(DriverArgs, CC1Args, Base + Arch + Slash + "include" + 565*e5dd7070Spatrick Slash + "c++" + Slash + "v1"); 566*e5dd7070Spatrick addSystemInclude(DriverArgs, CC1Args, 567*e5dd7070Spatrick Base + "include" + Slash + "c++" + Slash + "v1"); 568*e5dd7070Spatrick break; 569*e5dd7070Spatrick 570*e5dd7070Spatrick case ToolChain::CST_Libstdcxx: 571*e5dd7070Spatrick llvm::SmallVector<llvm::SmallString<1024>, 4> CppIncludeBases; 572*e5dd7070Spatrick CppIncludeBases.emplace_back(Base); 573*e5dd7070Spatrick llvm::sys::path::append(CppIncludeBases[0], Arch, "include", "c++"); 574*e5dd7070Spatrick CppIncludeBases.emplace_back(Base); 575*e5dd7070Spatrick llvm::sys::path::append(CppIncludeBases[1], Arch, "include", "c++", Ver); 576*e5dd7070Spatrick CppIncludeBases.emplace_back(Base); 577*e5dd7070Spatrick llvm::sys::path::append(CppIncludeBases[2], "include", "c++", Ver); 578*e5dd7070Spatrick CppIncludeBases.emplace_back(GccLibDir); 579*e5dd7070Spatrick llvm::sys::path::append(CppIncludeBases[3], "include", "c++"); 580*e5dd7070Spatrick for (auto &CppIncludeBase : CppIncludeBases) { 581*e5dd7070Spatrick addSystemInclude(DriverArgs, CC1Args, CppIncludeBase); 582*e5dd7070Spatrick CppIncludeBase += Slash; 583*e5dd7070Spatrick addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + Arch); 584*e5dd7070Spatrick addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + "backward"); 585*e5dd7070Spatrick } 586*e5dd7070Spatrick break; 587*e5dd7070Spatrick } 588*e5dd7070Spatrick } 589