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