1e5dd7070Spatrick //===--- MinGW.cpp - MinGWToolChain Implementation ------------------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick 
9e5dd7070Spatrick #include "MinGW.h"
10e5dd7070Spatrick #include "CommonArgs.h"
11e5dd7070Spatrick #include "clang/Config/config.h"
12e5dd7070Spatrick #include "clang/Driver/Compilation.h"
13e5dd7070Spatrick #include "clang/Driver/Driver.h"
14e5dd7070Spatrick #include "clang/Driver/DriverDiagnostic.h"
15a9ac8606Spatrick #include "clang/Driver/InputInfo.h"
16e5dd7070Spatrick #include "clang/Driver/Options.h"
17e5dd7070Spatrick #include "clang/Driver/SanitizerArgs.h"
18e5dd7070Spatrick #include "llvm/Option/ArgList.h"
19e5dd7070Spatrick #include "llvm/Support/FileSystem.h"
20e5dd7070Spatrick #include "llvm/Support/Path.h"
21ec727ea7Spatrick #include "llvm/Support/VirtualFileSystem.h"
22e5dd7070Spatrick #include <system_error>
23e5dd7070Spatrick 
24e5dd7070Spatrick using namespace clang::diag;
25e5dd7070Spatrick using namespace clang::driver;
26e5dd7070Spatrick using namespace clang;
27e5dd7070Spatrick using namespace llvm::opt;
28e5dd7070Spatrick 
29e5dd7070Spatrick /// MinGW Tools
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const30e5dd7070Spatrick void tools::MinGW::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
31e5dd7070Spatrick                                            const InputInfo &Output,
32e5dd7070Spatrick                                            const InputInfoList &Inputs,
33e5dd7070Spatrick                                            const ArgList &Args,
34e5dd7070Spatrick                                            const char *LinkingOutput) const {
35e5dd7070Spatrick   claimNoWarnArgs(Args);
36e5dd7070Spatrick   ArgStringList CmdArgs;
37e5dd7070Spatrick 
38e5dd7070Spatrick   if (getToolChain().getArch() == llvm::Triple::x86) {
39e5dd7070Spatrick     CmdArgs.push_back("--32");
40e5dd7070Spatrick   } else if (getToolChain().getArch() == llvm::Triple::x86_64) {
41e5dd7070Spatrick     CmdArgs.push_back("--64");
42e5dd7070Spatrick   }
43e5dd7070Spatrick 
44e5dd7070Spatrick   Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
45e5dd7070Spatrick 
46e5dd7070Spatrick   CmdArgs.push_back("-o");
47e5dd7070Spatrick   CmdArgs.push_back(Output.getFilename());
48e5dd7070Spatrick 
49e5dd7070Spatrick   for (const auto &II : Inputs)
50e5dd7070Spatrick     CmdArgs.push_back(II.getFilename());
51e5dd7070Spatrick 
52e5dd7070Spatrick   const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
53ec727ea7Spatrick   C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
54a9ac8606Spatrick                                          Exec, CmdArgs, Inputs, Output));
55e5dd7070Spatrick 
56e5dd7070Spatrick   if (Args.hasArg(options::OPT_gsplit_dwarf))
57e5dd7070Spatrick     SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
58a9ac8606Spatrick                    SplitDebugName(JA, Args, Inputs[0], Output));
59e5dd7070Spatrick }
60e5dd7070Spatrick 
AddLibGCC(const ArgList & Args,ArgStringList & CmdArgs) const61e5dd7070Spatrick void tools::MinGW::Linker::AddLibGCC(const ArgList &Args,
62e5dd7070Spatrick                                      ArgStringList &CmdArgs) const {
63e5dd7070Spatrick   if (Args.hasArg(options::OPT_mthreads))
64e5dd7070Spatrick     CmdArgs.push_back("-lmingwthrd");
65e5dd7070Spatrick   CmdArgs.push_back("-lmingw32");
66e5dd7070Spatrick 
67e5dd7070Spatrick   // Make use of compiler-rt if --rtlib option is used
68e5dd7070Spatrick   ToolChain::RuntimeLibType RLT = getToolChain().GetRuntimeLibType(Args);
69e5dd7070Spatrick   if (RLT == ToolChain::RLT_Libgcc) {
70e5dd7070Spatrick     bool Static = Args.hasArg(options::OPT_static_libgcc) ||
71e5dd7070Spatrick                   Args.hasArg(options::OPT_static);
72e5dd7070Spatrick     bool Shared = Args.hasArg(options::OPT_shared);
73e5dd7070Spatrick     bool CXX = getToolChain().getDriver().CCCIsCXX();
74e5dd7070Spatrick 
75e5dd7070Spatrick     if (Static || (!CXX && !Shared)) {
76e5dd7070Spatrick       CmdArgs.push_back("-lgcc");
77e5dd7070Spatrick       CmdArgs.push_back("-lgcc_eh");
78e5dd7070Spatrick     } else {
79e5dd7070Spatrick       CmdArgs.push_back("-lgcc_s");
80e5dd7070Spatrick       CmdArgs.push_back("-lgcc");
81e5dd7070Spatrick     }
82e5dd7070Spatrick   } else {
83e5dd7070Spatrick     AddRunTimeLibs(getToolChain(), getToolChain().getDriver(), CmdArgs, Args);
84e5dd7070Spatrick   }
85e5dd7070Spatrick 
86e5dd7070Spatrick   CmdArgs.push_back("-lmoldname");
87e5dd7070Spatrick   CmdArgs.push_back("-lmingwex");
88e5dd7070Spatrick   for (auto Lib : Args.getAllArgValues(options::OPT_l))
89*12c85518Srobert     if (StringRef(Lib).startswith("msvcr") ||
90*12c85518Srobert         StringRef(Lib).startswith("ucrt") ||
91*12c85518Srobert         StringRef(Lib).startswith("crtdll"))
92e5dd7070Spatrick       return;
93e5dd7070Spatrick   CmdArgs.push_back("-lmsvcrt");
94e5dd7070Spatrick }
95e5dd7070Spatrick 
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const96e5dd7070Spatrick void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
97e5dd7070Spatrick                                         const InputInfo &Output,
98e5dd7070Spatrick                                         const InputInfoList &Inputs,
99e5dd7070Spatrick                                         const ArgList &Args,
100e5dd7070Spatrick                                         const char *LinkingOutput) const {
101e5dd7070Spatrick   const ToolChain &TC = getToolChain();
102e5dd7070Spatrick   const Driver &D = TC.getDriver();
103*12c85518Srobert   const SanitizerArgs &Sanitize = TC.getSanitizerArgs(Args);
104e5dd7070Spatrick 
105e5dd7070Spatrick   ArgStringList CmdArgs;
106e5dd7070Spatrick 
107e5dd7070Spatrick   // Silence warning for "clang -g foo.o -o foo"
108e5dd7070Spatrick   Args.ClaimAllArgs(options::OPT_g_Group);
109e5dd7070Spatrick   // and "clang -emit-llvm foo.o -o foo"
110e5dd7070Spatrick   Args.ClaimAllArgs(options::OPT_emit_llvm);
111e5dd7070Spatrick   // and for "clang -w foo.o -o foo". Other warning options are already
112e5dd7070Spatrick   // handled somewhere else.
113e5dd7070Spatrick   Args.ClaimAllArgs(options::OPT_w);
114e5dd7070Spatrick 
115e5dd7070Spatrick   if (!D.SysRoot.empty())
116e5dd7070Spatrick     CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
117e5dd7070Spatrick 
118e5dd7070Spatrick   if (Args.hasArg(options::OPT_s))
119e5dd7070Spatrick     CmdArgs.push_back("-s");
120e5dd7070Spatrick 
121e5dd7070Spatrick   CmdArgs.push_back("-m");
122e5dd7070Spatrick   switch (TC.getArch()) {
123e5dd7070Spatrick   case llvm::Triple::x86:
124e5dd7070Spatrick     CmdArgs.push_back("i386pe");
125e5dd7070Spatrick     break;
126e5dd7070Spatrick   case llvm::Triple::x86_64:
127e5dd7070Spatrick     CmdArgs.push_back("i386pep");
128e5dd7070Spatrick     break;
129e5dd7070Spatrick   case llvm::Triple::arm:
130e5dd7070Spatrick   case llvm::Triple::thumb:
131e5dd7070Spatrick     // FIXME: this is incorrect for WinCE
132e5dd7070Spatrick     CmdArgs.push_back("thumb2pe");
133e5dd7070Spatrick     break;
134e5dd7070Spatrick   case llvm::Triple::aarch64:
135e5dd7070Spatrick     CmdArgs.push_back("arm64pe");
136e5dd7070Spatrick     break;
137e5dd7070Spatrick   default:
138e5dd7070Spatrick     llvm_unreachable("Unsupported target architecture.");
139e5dd7070Spatrick   }
140e5dd7070Spatrick 
141a9ac8606Spatrick   Arg *SubsysArg =
142a9ac8606Spatrick       Args.getLastArg(options::OPT_mwindows, options::OPT_mconsole);
143a9ac8606Spatrick   if (SubsysArg && SubsysArg->getOption().matches(options::OPT_mwindows)) {
144e5dd7070Spatrick     CmdArgs.push_back("--subsystem");
145e5dd7070Spatrick     CmdArgs.push_back("windows");
146a9ac8606Spatrick   } else if (SubsysArg &&
147a9ac8606Spatrick              SubsysArg->getOption().matches(options::OPT_mconsole)) {
148e5dd7070Spatrick     CmdArgs.push_back("--subsystem");
149e5dd7070Spatrick     CmdArgs.push_back("console");
150e5dd7070Spatrick   }
151e5dd7070Spatrick 
152e5dd7070Spatrick   if (Args.hasArg(options::OPT_mdll))
153e5dd7070Spatrick     CmdArgs.push_back("--dll");
154e5dd7070Spatrick   else if (Args.hasArg(options::OPT_shared))
155e5dd7070Spatrick     CmdArgs.push_back("--shared");
156e5dd7070Spatrick   if (Args.hasArg(options::OPT_static))
157e5dd7070Spatrick     CmdArgs.push_back("-Bstatic");
158e5dd7070Spatrick   else
159e5dd7070Spatrick     CmdArgs.push_back("-Bdynamic");
160e5dd7070Spatrick   if (Args.hasArg(options::OPT_mdll) || Args.hasArg(options::OPT_shared)) {
161e5dd7070Spatrick     CmdArgs.push_back("-e");
162e5dd7070Spatrick     if (TC.getArch() == llvm::Triple::x86)
163e5dd7070Spatrick       CmdArgs.push_back("_DllMainCRTStartup@12");
164e5dd7070Spatrick     else
165e5dd7070Spatrick       CmdArgs.push_back("DllMainCRTStartup");
166e5dd7070Spatrick     CmdArgs.push_back("--enable-auto-image-base");
167e5dd7070Spatrick   }
168e5dd7070Spatrick 
169*12c85518Srobert   if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
170*12c85518Srobert     CmdArgs.push_back("--no-demangle");
171*12c85518Srobert 
172*12c85518Srobert   if (Arg *A = Args.getLastArg(options::OPT_mguard_EQ)) {
173*12c85518Srobert     StringRef GuardArgs = A->getValue();
174*12c85518Srobert     if (GuardArgs == "none")
175*12c85518Srobert       CmdArgs.push_back("--no-guard-cf");
176*12c85518Srobert     else if (GuardArgs == "cf" || GuardArgs == "cf-nochecks")
177*12c85518Srobert       CmdArgs.push_back("--guard-cf");
178*12c85518Srobert     else
179*12c85518Srobert       D.Diag(diag::err_drv_unsupported_option_argument)
180*12c85518Srobert           << A->getSpelling() << GuardArgs;
181*12c85518Srobert   }
182*12c85518Srobert 
183e5dd7070Spatrick   CmdArgs.push_back("-o");
184e5dd7070Spatrick   const char *OutputFile = Output.getFilename();
185e5dd7070Spatrick   // GCC implicitly adds an .exe extension if it is given an output file name
186a9ac8606Spatrick   // that lacks an extension.
187a9ac8606Spatrick   // GCC used to do this only when the compiler itself runs on windows, but
188a9ac8606Spatrick   // since GCC 8 it does the same when cross compiling as well.
189a9ac8606Spatrick   if (!llvm::sys::path::has_extension(OutputFile)) {
190e5dd7070Spatrick     CmdArgs.push_back(Args.MakeArgString(Twine(OutputFile) + ".exe"));
191a9ac8606Spatrick     OutputFile = CmdArgs.back();
192a9ac8606Spatrick   } else
193e5dd7070Spatrick     CmdArgs.push_back(OutputFile);
194e5dd7070Spatrick 
195e5dd7070Spatrick   Args.AddAllArgs(CmdArgs, options::OPT_e);
196e5dd7070Spatrick   // FIXME: add -N, -n flags
197e5dd7070Spatrick   Args.AddLastArg(CmdArgs, options::OPT_r);
198e5dd7070Spatrick   Args.AddLastArg(CmdArgs, options::OPT_s);
199e5dd7070Spatrick   Args.AddLastArg(CmdArgs, options::OPT_t);
200e5dd7070Spatrick   Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
201e5dd7070Spatrick   Args.AddLastArg(CmdArgs, options::OPT_Z_Flag);
202e5dd7070Spatrick 
203*12c85518Srobert   // Add asan_dynamic as the first import lib before other libs. This allows
204*12c85518Srobert   // asan to be initialized as early as possible to increase its instrumentation
205*12c85518Srobert   // coverage to include other user DLLs which has not been built with asan.
206*12c85518Srobert   if (Sanitize.needsAsanRt() && !Args.hasArg(options::OPT_nostdlib) &&
207*12c85518Srobert       !Args.hasArg(options::OPT_nodefaultlibs)) {
208*12c85518Srobert     // MinGW always links against a shared MSVCRT.
209*12c85518Srobert     CmdArgs.push_back(
210*12c85518Srobert         TC.getCompilerRTArgString(Args, "asan_dynamic", ToolChain::FT_Shared));
211*12c85518Srobert   }
212*12c85518Srobert 
213e5dd7070Spatrick   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
214e5dd7070Spatrick     if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_mdll)) {
215e5dd7070Spatrick       CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("dllcrt2.o")));
216e5dd7070Spatrick     } else {
217e5dd7070Spatrick       if (Args.hasArg(options::OPT_municode))
218e5dd7070Spatrick         CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2u.o")));
219e5dd7070Spatrick       else
220e5dd7070Spatrick         CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2.o")));
221e5dd7070Spatrick     }
222e5dd7070Spatrick     if (Args.hasArg(options::OPT_pg))
223e5dd7070Spatrick       CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("gcrt2.o")));
224e5dd7070Spatrick     CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o")));
225e5dd7070Spatrick   }
226e5dd7070Spatrick 
227e5dd7070Spatrick   Args.AddAllArgs(CmdArgs, options::OPT_L);
228e5dd7070Spatrick   TC.AddFilePathLibArgs(Args, CmdArgs);
229ec727ea7Spatrick 
230ec727ea7Spatrick   // Add the compiler-rt library directories if they exist to help
231ec727ea7Spatrick   // the linker find the various sanitizer, builtin, and profiling runtimes.
232ec727ea7Spatrick   for (const auto &LibPath : TC.getLibraryPaths()) {
233ec727ea7Spatrick     if (TC.getVFS().exists(LibPath))
234ec727ea7Spatrick       CmdArgs.push_back(Args.MakeArgString("-L" + LibPath));
235ec727ea7Spatrick   }
236ec727ea7Spatrick   auto CRTPath = TC.getCompilerRTPath();
237ec727ea7Spatrick   if (TC.getVFS().exists(CRTPath))
238ec727ea7Spatrick     CmdArgs.push_back(Args.MakeArgString("-L" + CRTPath));
239ec727ea7Spatrick 
240e5dd7070Spatrick   AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
241e5dd7070Spatrick 
242*12c85518Srobert   if (C.getDriver().IsFlangMode()) {
243*12c85518Srobert     addFortranRuntimeLibraryPath(TC, Args, CmdArgs);
244*12c85518Srobert     addFortranRuntimeLibs(TC, CmdArgs);
245*12c85518Srobert   }
246*12c85518Srobert 
247e5dd7070Spatrick   // TODO: Add profile stuff here
248e5dd7070Spatrick 
249e5dd7070Spatrick   if (TC.ShouldLinkCXXStdlib(Args)) {
250e5dd7070Spatrick     bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
251e5dd7070Spatrick                                !Args.hasArg(options::OPT_static);
252e5dd7070Spatrick     if (OnlyLibstdcxxStatic)
253e5dd7070Spatrick       CmdArgs.push_back("-Bstatic");
254e5dd7070Spatrick     TC.AddCXXStdlibLibArgs(Args, CmdArgs);
255e5dd7070Spatrick     if (OnlyLibstdcxxStatic)
256e5dd7070Spatrick       CmdArgs.push_back("-Bdynamic");
257e5dd7070Spatrick   }
258e5dd7070Spatrick 
259e5dd7070Spatrick   bool HasWindowsApp = false;
260e5dd7070Spatrick   for (auto Lib : Args.getAllArgValues(options::OPT_l)) {
261e5dd7070Spatrick     if (Lib == "windowsapp") {
262e5dd7070Spatrick       HasWindowsApp = true;
263e5dd7070Spatrick       break;
264e5dd7070Spatrick     }
265e5dd7070Spatrick   }
266e5dd7070Spatrick 
267e5dd7070Spatrick   if (!Args.hasArg(options::OPT_nostdlib)) {
268e5dd7070Spatrick     if (!Args.hasArg(options::OPT_nodefaultlibs)) {
269e5dd7070Spatrick       if (Args.hasArg(options::OPT_static))
270e5dd7070Spatrick         CmdArgs.push_back("--start-group");
271e5dd7070Spatrick 
272e5dd7070Spatrick       if (Args.hasArg(options::OPT_fstack_protector) ||
273e5dd7070Spatrick           Args.hasArg(options::OPT_fstack_protector_strong) ||
274e5dd7070Spatrick           Args.hasArg(options::OPT_fstack_protector_all)) {
275e5dd7070Spatrick         CmdArgs.push_back("-lssp_nonshared");
276e5dd7070Spatrick         CmdArgs.push_back("-lssp");
277e5dd7070Spatrick       }
278e5dd7070Spatrick 
279e5dd7070Spatrick       if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
280e5dd7070Spatrick                        options::OPT_fno_openmp, false)) {
281e5dd7070Spatrick         switch (TC.getDriver().getOpenMPRuntime(Args)) {
282e5dd7070Spatrick         case Driver::OMPRT_OMP:
283e5dd7070Spatrick           CmdArgs.push_back("-lomp");
284e5dd7070Spatrick           break;
285e5dd7070Spatrick         case Driver::OMPRT_IOMP5:
286e5dd7070Spatrick           CmdArgs.push_back("-liomp5md");
287e5dd7070Spatrick           break;
288e5dd7070Spatrick         case Driver::OMPRT_GOMP:
289e5dd7070Spatrick           CmdArgs.push_back("-lgomp");
290e5dd7070Spatrick           break;
291e5dd7070Spatrick         case Driver::OMPRT_Unknown:
292e5dd7070Spatrick           // Already diagnosed.
293e5dd7070Spatrick           break;
294e5dd7070Spatrick         }
295e5dd7070Spatrick       }
296e5dd7070Spatrick 
297e5dd7070Spatrick       AddLibGCC(Args, CmdArgs);
298e5dd7070Spatrick 
299e5dd7070Spatrick       if (Args.hasArg(options::OPT_pg))
300e5dd7070Spatrick         CmdArgs.push_back("-lgmon");
301e5dd7070Spatrick 
302e5dd7070Spatrick       if (Args.hasArg(options::OPT_pthread))
303e5dd7070Spatrick         CmdArgs.push_back("-lpthread");
304e5dd7070Spatrick 
305e5dd7070Spatrick       if (Sanitize.needsAsanRt()) {
306e5dd7070Spatrick         // MinGW always links against a shared MSVCRT.
307e5dd7070Spatrick         CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dynamic",
308e5dd7070Spatrick                                                     ToolChain::FT_Shared));
309e5dd7070Spatrick         CmdArgs.push_back(
310e5dd7070Spatrick             TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk"));
311e5dd7070Spatrick         CmdArgs.push_back("--require-defined");
312e5dd7070Spatrick         CmdArgs.push_back(TC.getArch() == llvm::Triple::x86
313e5dd7070Spatrick                               ? "___asan_seh_interceptor"
314e5dd7070Spatrick                               : "__asan_seh_interceptor");
315e5dd7070Spatrick         // Make sure the linker consider all object files from the dynamic
316e5dd7070Spatrick         // runtime thunk.
317e5dd7070Spatrick         CmdArgs.push_back("--whole-archive");
318e5dd7070Spatrick         CmdArgs.push_back(
319e5dd7070Spatrick             TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk"));
320e5dd7070Spatrick         CmdArgs.push_back("--no-whole-archive");
321e5dd7070Spatrick       }
322e5dd7070Spatrick 
323e5dd7070Spatrick       TC.addProfileRTLibs(Args, CmdArgs);
324e5dd7070Spatrick 
325e5dd7070Spatrick       if (!HasWindowsApp) {
326e5dd7070Spatrick         // Add system libraries. If linking to libwindowsapp.a, that import
327e5dd7070Spatrick         // library replaces all these and we shouldn't accidentally try to
328e5dd7070Spatrick         // link to the normal desktop mode dlls.
329e5dd7070Spatrick         if (Args.hasArg(options::OPT_mwindows)) {
330e5dd7070Spatrick           CmdArgs.push_back("-lgdi32");
331e5dd7070Spatrick           CmdArgs.push_back("-lcomdlg32");
332e5dd7070Spatrick         }
333e5dd7070Spatrick         CmdArgs.push_back("-ladvapi32");
334e5dd7070Spatrick         CmdArgs.push_back("-lshell32");
335e5dd7070Spatrick         CmdArgs.push_back("-luser32");
336e5dd7070Spatrick         CmdArgs.push_back("-lkernel32");
337e5dd7070Spatrick       }
338e5dd7070Spatrick 
339ec727ea7Spatrick       if (Args.hasArg(options::OPT_static)) {
340e5dd7070Spatrick         CmdArgs.push_back("--end-group");
341ec727ea7Spatrick       } else {
342e5dd7070Spatrick         AddLibGCC(Args, CmdArgs);
343ec727ea7Spatrick         if (!HasWindowsApp)
344ec727ea7Spatrick           CmdArgs.push_back("-lkernel32");
345ec727ea7Spatrick       }
346e5dd7070Spatrick     }
347e5dd7070Spatrick 
348e5dd7070Spatrick     if (!Args.hasArg(options::OPT_nostartfiles)) {
349e5dd7070Spatrick       // Add crtfastmath.o if available and fast math is enabled.
350ec727ea7Spatrick       TC.addFastMathRuntimeIfAvailable(Args, CmdArgs);
351e5dd7070Spatrick 
352e5dd7070Spatrick       CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o")));
353e5dd7070Spatrick     }
354e5dd7070Spatrick   }
355e5dd7070Spatrick   const char *Exec = Args.MakeArgString(TC.GetLinkerPath());
356a9ac8606Spatrick   C.addCommand(std::make_unique<Command>(JA, *this,
357a9ac8606Spatrick                                          ResponseFileSupport::AtFileUTF8(),
358a9ac8606Spatrick                                          Exec, CmdArgs, Inputs, Output));
359e5dd7070Spatrick }
360e5dd7070Spatrick 
isCrossCompiling(const llvm::Triple & T,bool RequireArchMatch)361*12c85518Srobert static bool isCrossCompiling(const llvm::Triple &T, bool RequireArchMatch) {
362*12c85518Srobert   llvm::Triple HostTriple(llvm::Triple::normalize(LLVM_HOST_TRIPLE));
363*12c85518Srobert   if (HostTriple.getOS() != llvm::Triple::Win32)
364*12c85518Srobert     return true;
365*12c85518Srobert   if (RequireArchMatch && HostTriple.getArch() != T.getArch())
366*12c85518Srobert     return true;
367*12c85518Srobert   return false;
368*12c85518Srobert }
369*12c85518Srobert 
370e5dd7070Spatrick // Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple.
findGccVersion(StringRef LibDir,std::string & GccLibDir,std::string & Ver,toolchains::Generic_GCC::GCCVersion & Version)371e5dd7070Spatrick static bool findGccVersion(StringRef LibDir, std::string &GccLibDir,
372*12c85518Srobert                            std::string &Ver,
373*12c85518Srobert                            toolchains::Generic_GCC::GCCVersion &Version) {
374*12c85518Srobert   Version = toolchains::Generic_GCC::GCCVersion::Parse("0.0.0");
375e5dd7070Spatrick   std::error_code EC;
376e5dd7070Spatrick   for (llvm::sys::fs::directory_iterator LI(LibDir, EC), LE; !EC && LI != LE;
377e5dd7070Spatrick        LI = LI.increment(EC)) {
378e5dd7070Spatrick     StringRef VersionText = llvm::sys::path::filename(LI->path());
379e5dd7070Spatrick     auto CandidateVersion =
380e5dd7070Spatrick         toolchains::Generic_GCC::GCCVersion::Parse(VersionText);
381e5dd7070Spatrick     if (CandidateVersion.Major == -1)
382e5dd7070Spatrick       continue;
383e5dd7070Spatrick     if (CandidateVersion <= Version)
384e5dd7070Spatrick       continue;
385a9ac8606Spatrick     Version = CandidateVersion;
386ec727ea7Spatrick     Ver = std::string(VersionText);
387e5dd7070Spatrick     GccLibDir = LI->path();
388e5dd7070Spatrick   }
389e5dd7070Spatrick   return Ver.size();
390e5dd7070Spatrick }
391e5dd7070Spatrick 
getLiteralTriple(const Driver & D,const llvm::Triple & T)392*12c85518Srobert static llvm::Triple getLiteralTriple(const Driver &D, const llvm::Triple &T) {
393*12c85518Srobert   llvm::Triple LiteralTriple(D.getTargetTriple());
394*12c85518Srobert   // The arch portion of the triple may be overridden by -m32/-m64.
395*12c85518Srobert   LiteralTriple.setArchName(T.getArchName());
396*12c85518Srobert   return LiteralTriple;
397*12c85518Srobert }
398*12c85518Srobert 
findGccLibDir(const llvm::Triple & LiteralTriple)399*12c85518Srobert void toolchains::MinGW::findGccLibDir(const llvm::Triple &LiteralTriple) {
400*12c85518Srobert   llvm::SmallVector<llvm::SmallString<32>, 5> SubdirNames;
401*12c85518Srobert   SubdirNames.emplace_back(LiteralTriple.str());
402*12c85518Srobert   SubdirNames.emplace_back(getTriple().str());
403*12c85518Srobert   SubdirNames.emplace_back(getTriple().getArchName());
404*12c85518Srobert   SubdirNames.back() += "-w64-mingw32";
405*12c85518Srobert   SubdirNames.emplace_back(getTriple().getArchName());
406*12c85518Srobert   SubdirNames.back() += "-w64-mingw32ucrt";
407*12c85518Srobert   SubdirNames.emplace_back("mingw32");
408*12c85518Srobert   if (SubdirName.empty()) {
409*12c85518Srobert     SubdirName = getTriple().getArchName();
410*12c85518Srobert     SubdirName += "-w64-mingw32";
411*12c85518Srobert   }
412e5dd7070Spatrick   // lib: Arch Linux, Ubuntu, Windows
413e5dd7070Spatrick   // lib64: openSUSE Linux
414e5dd7070Spatrick   for (StringRef CandidateLib : {"lib", "lib64"}) {
415*12c85518Srobert     for (StringRef CandidateSysroot : SubdirNames) {
416e5dd7070Spatrick       llvm::SmallString<1024> LibDir(Base);
417*12c85518Srobert       llvm::sys::path::append(LibDir, CandidateLib, "gcc", CandidateSysroot);
418*12c85518Srobert       if (findGccVersion(LibDir, GccLibDir, Ver, GccVer)) {
419*12c85518Srobert         SubdirName = std::string(CandidateSysroot);
420e5dd7070Spatrick         return;
421e5dd7070Spatrick       }
422e5dd7070Spatrick     }
423e5dd7070Spatrick   }
424e5dd7070Spatrick }
425e5dd7070Spatrick 
findGcc(const llvm::Triple & LiteralTriple,const llvm::Triple & T)426*12c85518Srobert static llvm::ErrorOr<std::string> findGcc(const llvm::Triple &LiteralTriple,
427*12c85518Srobert                                           const llvm::Triple &T) {
428*12c85518Srobert   llvm::SmallVector<llvm::SmallString<32>, 5> Gccs;
429*12c85518Srobert   Gccs.emplace_back(LiteralTriple.str());
430*12c85518Srobert   Gccs.back() += "-gcc";
431*12c85518Srobert   Gccs.emplace_back(T.str());
432*12c85518Srobert   Gccs.back() += "-gcc";
433*12c85518Srobert   Gccs.emplace_back(T.getArchName());
434*12c85518Srobert   Gccs.back() += "-w64-mingw32-gcc";
435*12c85518Srobert   Gccs.emplace_back(T.getArchName());
436*12c85518Srobert   Gccs.back() += "-w64-mingw32ucrt-gcc";
437e5dd7070Spatrick   Gccs.emplace_back("mingw32-gcc");
438e5dd7070Spatrick   // Please do not add "gcc" here
439e5dd7070Spatrick   for (StringRef CandidateGcc : Gccs)
440e5dd7070Spatrick     if (llvm::ErrorOr<std::string> GPPName = llvm::sys::findProgramByName(CandidateGcc))
441e5dd7070Spatrick       return GPPName;
442e5dd7070Spatrick   return make_error_code(std::errc::no_such_file_or_directory);
443e5dd7070Spatrick }
444e5dd7070Spatrick 
445*12c85518Srobert static llvm::ErrorOr<std::string>
findClangRelativeSysroot(const Driver & D,const llvm::Triple & LiteralTriple,const llvm::Triple & T,std::string & SubdirName)446*12c85518Srobert findClangRelativeSysroot(const Driver &D, const llvm::Triple &LiteralTriple,
447*12c85518Srobert                          const llvm::Triple &T, std::string &SubdirName) {
448*12c85518Srobert   llvm::SmallVector<llvm::SmallString<32>, 4> Subdirs;
449*12c85518Srobert   Subdirs.emplace_back(LiteralTriple.str());
450*12c85518Srobert   Subdirs.emplace_back(T.str());
451*12c85518Srobert   Subdirs.emplace_back(T.getArchName());
452*12c85518Srobert   Subdirs.back() += "-w64-mingw32";
453*12c85518Srobert   Subdirs.emplace_back(T.getArchName());
454*12c85518Srobert   Subdirs.back() += "-w64-mingw32ucrt";
455*12c85518Srobert   StringRef ClangRoot = llvm::sys::path::parent_path(D.getInstalledDir());
456e5dd7070Spatrick   StringRef Sep = llvm::sys::path::get_separator();
457e5dd7070Spatrick   for (StringRef CandidateSubdir : Subdirs) {
458e5dd7070Spatrick     if (llvm::sys::fs::is_directory(ClangRoot + Sep + CandidateSubdir)) {
459*12c85518Srobert       SubdirName = std::string(CandidateSubdir);
460e5dd7070Spatrick       return (ClangRoot + Sep + CandidateSubdir).str();
461e5dd7070Spatrick     }
462e5dd7070Spatrick   }
463e5dd7070Spatrick   return make_error_code(std::errc::no_such_file_or_directory);
464e5dd7070Spatrick }
465e5dd7070Spatrick 
MinGW(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)466e5dd7070Spatrick toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple,
467e5dd7070Spatrick                          const ArgList &Args)
468ec727ea7Spatrick     : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args),
469ec727ea7Spatrick       RocmInstallation(D, Triple, Args) {
470e5dd7070Spatrick   getProgramPaths().push_back(getDriver().getInstalledDir());
471e5dd7070Spatrick 
472*12c85518Srobert   // The sequence for detecting a sysroot here should be kept in sync with
473*12c85518Srobert   // the testTriple function below.
474*12c85518Srobert   llvm::Triple LiteralTriple = getLiteralTriple(D, getTriple());
475e5dd7070Spatrick   if (getDriver().SysRoot.size())
476e5dd7070Spatrick     Base = getDriver().SysRoot;
477e5dd7070Spatrick   // Look for <clang-bin>/../<triplet>; if found, use <clang-bin>/.. as the
478e5dd7070Spatrick   // base as it could still be a base for a gcc setup with libgcc.
479*12c85518Srobert   else if (llvm::ErrorOr<std::string> TargetSubdir = findClangRelativeSysroot(
480*12c85518Srobert                getDriver(), LiteralTriple, getTriple(), SubdirName))
481ec727ea7Spatrick     Base = std::string(llvm::sys::path::parent_path(TargetSubdir.get()));
482*12c85518Srobert   else if (llvm::ErrorOr<std::string> GPPName =
483*12c85518Srobert                findGcc(LiteralTriple, getTriple()))
484ec727ea7Spatrick     Base = std::string(llvm::sys::path::parent_path(
485ec727ea7Spatrick         llvm::sys::path::parent_path(GPPName.get())));
486e5dd7070Spatrick   else
487ec727ea7Spatrick     Base = std::string(
488ec727ea7Spatrick         llvm::sys::path::parent_path(getDriver().getInstalledDir()));
489e5dd7070Spatrick 
490e5dd7070Spatrick   Base += llvm::sys::path::get_separator();
491*12c85518Srobert   findGccLibDir(LiteralTriple);
492*12c85518Srobert   TripleDirName = SubdirName;
493e5dd7070Spatrick   // GccLibDir must precede Base/lib so that the
494e5dd7070Spatrick   // correct crtbegin.o ,cetend.o would be found.
495e5dd7070Spatrick   getFilePaths().push_back(GccLibDir);
496*12c85518Srobert 
497*12c85518Srobert   // openSUSE/Fedora
498*12c85518Srobert   std::string CandidateSubdir = SubdirName + "/sys-root/mingw";
499*12c85518Srobert   if (getDriver().getVFS().exists(Base + CandidateSubdir))
500*12c85518Srobert     SubdirName = CandidateSubdir;
501*12c85518Srobert 
502e5dd7070Spatrick   getFilePaths().push_back(
503*12c85518Srobert       (Base + SubdirName + llvm::sys::path::get_separator() + "lib").str());
504*12c85518Srobert 
505*12c85518Srobert   // Gentoo
506*12c85518Srobert   getFilePaths().push_back(
507*12c85518Srobert       (Base + SubdirName + llvm::sys::path::get_separator() + "mingw/lib").str());
508*12c85518Srobert 
509*12c85518Srobert   // Only include <base>/lib if we're not cross compiling (not even for
510*12c85518Srobert   // windows->windows to a different arch), or if the sysroot has been set
511*12c85518Srobert   // (where we presume the user has pointed it at an arch specific
512*12c85518Srobert   // subdirectory).
513*12c85518Srobert   if (!::isCrossCompiling(getTriple(), /*RequireArchMatch=*/true) ||
514*12c85518Srobert       getDriver().SysRoot.size())
515e5dd7070Spatrick     getFilePaths().push_back(Base + "lib");
516e5dd7070Spatrick 
517e5dd7070Spatrick   NativeLLVMSupport =
518e5dd7070Spatrick       Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER)
519a9ac8606Spatrick           .equals_insensitive("lld");
520e5dd7070Spatrick }
521e5dd7070Spatrick 
IsIntegratedAssemblerDefault() const522e5dd7070Spatrick bool toolchains::MinGW::IsIntegratedAssemblerDefault() const { return true; }
523e5dd7070Spatrick 
getTool(Action::ActionClass AC) const524e5dd7070Spatrick Tool *toolchains::MinGW::getTool(Action::ActionClass AC) const {
525e5dd7070Spatrick   switch (AC) {
526e5dd7070Spatrick   case Action::PreprocessJobClass:
527e5dd7070Spatrick     if (!Preprocessor)
528e5dd7070Spatrick       Preprocessor.reset(new tools::gcc::Preprocessor(*this));
529e5dd7070Spatrick     return Preprocessor.get();
530e5dd7070Spatrick   case Action::CompileJobClass:
531e5dd7070Spatrick     if (!Compiler)
532e5dd7070Spatrick       Compiler.reset(new tools::gcc::Compiler(*this));
533e5dd7070Spatrick     return Compiler.get();
534e5dd7070Spatrick   default:
535e5dd7070Spatrick     return ToolChain::getTool(AC);
536e5dd7070Spatrick   }
537e5dd7070Spatrick }
538e5dd7070Spatrick 
buildAssembler() const539e5dd7070Spatrick Tool *toolchains::MinGW::buildAssembler() const {
540e5dd7070Spatrick   return new tools::MinGW::Assembler(*this);
541e5dd7070Spatrick }
542e5dd7070Spatrick 
buildLinker() const543e5dd7070Spatrick Tool *toolchains::MinGW::buildLinker() const {
544e5dd7070Spatrick   return new tools::MinGW::Linker(*this);
545e5dd7070Spatrick }
546e5dd7070Spatrick 
HasNativeLLVMSupport() const547e5dd7070Spatrick bool toolchains::MinGW::HasNativeLLVMSupport() const {
548e5dd7070Spatrick   return NativeLLVMSupport;
549e5dd7070Spatrick }
550e5dd7070Spatrick 
551*12c85518Srobert ToolChain::UnwindTableLevel
getDefaultUnwindTableLevel(const ArgList & Args) const552*12c85518Srobert toolchains::MinGW::getDefaultUnwindTableLevel(const ArgList &Args) const {
553e5dd7070Spatrick   Arg *ExceptionArg = Args.getLastArg(options::OPT_fsjlj_exceptions,
554e5dd7070Spatrick                                       options::OPT_fseh_exceptions,
555e5dd7070Spatrick                                       options::OPT_fdwarf_exceptions);
556e5dd7070Spatrick   if (ExceptionArg &&
557e5dd7070Spatrick       ExceptionArg->getOption().matches(options::OPT_fseh_exceptions))
558*12c85518Srobert     return UnwindTableLevel::Asynchronous;
559*12c85518Srobert 
560*12c85518Srobert   if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::arm ||
561*12c85518Srobert       getArch() == llvm::Triple::thumb || getArch() == llvm::Triple::aarch64)
562*12c85518Srobert     return UnwindTableLevel::Asynchronous;
563*12c85518Srobert   return UnwindTableLevel::None;
564*12c85518Srobert }
565*12c85518Srobert 
isPICDefault() const566*12c85518Srobert bool toolchains::MinGW::isPICDefault() const {
567e5dd7070Spatrick   return getArch() == llvm::Triple::x86_64 ||
568e5dd7070Spatrick          getArch() == llvm::Triple::aarch64;
569e5dd7070Spatrick }
570e5dd7070Spatrick 
isPIEDefault(const llvm::opt::ArgList & Args) const571*12c85518Srobert bool toolchains::MinGW::isPIEDefault(const llvm::opt::ArgList &Args) const {
572*12c85518Srobert   return false;
573e5dd7070Spatrick }
574e5dd7070Spatrick 
isPICDefaultForced() const575*12c85518Srobert bool toolchains::MinGW::isPICDefaultForced() const { return true; }
576e5dd7070Spatrick 
577e5dd7070Spatrick llvm::ExceptionHandling
GetExceptionModel(const ArgList & Args) const578e5dd7070Spatrick toolchains::MinGW::GetExceptionModel(const ArgList &Args) const {
579*12c85518Srobert   if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::aarch64 ||
580*12c85518Srobert       getArch() == llvm::Triple::arm || getArch() == llvm::Triple::thumb)
581e5dd7070Spatrick     return llvm::ExceptionHandling::WinEH;
582e5dd7070Spatrick   return llvm::ExceptionHandling::DwarfCFI;
583e5dd7070Spatrick }
584e5dd7070Spatrick 
getSupportedSanitizers() const585e5dd7070Spatrick SanitizerMask toolchains::MinGW::getSupportedSanitizers() const {
586e5dd7070Spatrick   SanitizerMask Res = ToolChain::getSupportedSanitizers();
587e5dd7070Spatrick   Res |= SanitizerKind::Address;
588e5dd7070Spatrick   Res |= SanitizerKind::PointerCompare;
589e5dd7070Spatrick   Res |= SanitizerKind::PointerSubtract;
590a9ac8606Spatrick   Res |= SanitizerKind::Vptr;
591e5dd7070Spatrick   return Res;
592e5dd7070Spatrick }
593e5dd7070Spatrick 
AddCudaIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const594e5dd7070Spatrick void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs,
595e5dd7070Spatrick                                            ArgStringList &CC1Args) const {
596e5dd7070Spatrick   CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
597e5dd7070Spatrick }
598e5dd7070Spatrick 
AddHIPIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const599ec727ea7Spatrick void toolchains::MinGW::AddHIPIncludeArgs(const ArgList &DriverArgs,
600ec727ea7Spatrick                                           ArgStringList &CC1Args) const {
601ec727ea7Spatrick   RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
602ec727ea7Spatrick }
603ec727ea7Spatrick 
printVerboseInfo(raw_ostream & OS) const604e5dd7070Spatrick void toolchains::MinGW::printVerboseInfo(raw_ostream &OS) const {
605e5dd7070Spatrick   CudaInstallation.print(OS);
606ec727ea7Spatrick   RocmInstallation.print(OS);
607e5dd7070Spatrick }
608e5dd7070Spatrick 
609e5dd7070Spatrick // Include directories for various hosts:
610e5dd7070Spatrick 
611e5dd7070Spatrick // Windows, mingw.org
612e5dd7070Spatrick // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++
613e5dd7070Spatrick // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\mingw32
614e5dd7070Spatrick // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\backward
615e5dd7070Spatrick // c:\mingw\include
616e5dd7070Spatrick // c:\mingw\mingw32\include
617e5dd7070Spatrick 
618e5dd7070Spatrick // Windows, mingw-w64 mingw-builds
619e5dd7070Spatrick // c:\mingw32\i686-w64-mingw32\include
620e5dd7070Spatrick // c:\mingw32\i686-w64-mingw32\include\c++
621e5dd7070Spatrick // c:\mingw32\i686-w64-mingw32\include\c++\i686-w64-mingw32
622e5dd7070Spatrick // c:\mingw32\i686-w64-mingw32\include\c++\backward
623e5dd7070Spatrick 
624e5dd7070Spatrick // Windows, mingw-w64 msys2
625e5dd7070Spatrick // c:\msys64\mingw32\include
626e5dd7070Spatrick // c:\msys64\mingw32\i686-w64-mingw32\include
627e5dd7070Spatrick // c:\msys64\mingw32\include\c++\4.9.2
628e5dd7070Spatrick // c:\msys64\mingw32\include\c++\4.9.2\i686-w64-mingw32
629e5dd7070Spatrick // c:\msys64\mingw32\include\c++\4.9.2\backward
630e5dd7070Spatrick 
631e5dd7070Spatrick // openSUSE
632e5dd7070Spatrick // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++
633e5dd7070Spatrick // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/x86_64-w64-mingw32
634e5dd7070Spatrick // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/backward
635e5dd7070Spatrick // /usr/x86_64-w64-mingw32/sys-root/mingw/include
636e5dd7070Spatrick 
637e5dd7070Spatrick // Arch Linux
638e5dd7070Spatrick // /usr/i686-w64-mingw32/include/c++/5.1.0
639e5dd7070Spatrick // /usr/i686-w64-mingw32/include/c++/5.1.0/i686-w64-mingw32
640e5dd7070Spatrick // /usr/i686-w64-mingw32/include/c++/5.1.0/backward
641e5dd7070Spatrick // /usr/i686-w64-mingw32/include
642e5dd7070Spatrick 
643e5dd7070Spatrick // Ubuntu
644e5dd7070Spatrick // /usr/include/c++/4.8
645e5dd7070Spatrick // /usr/include/c++/4.8/x86_64-w64-mingw32
646e5dd7070Spatrick // /usr/include/c++/4.8/backward
647e5dd7070Spatrick // /usr/x86_64-w64-mingw32/include
648e5dd7070Spatrick 
649*12c85518Srobert // Fedora
650*12c85518Srobert // /usr/x86_64-w64-mingw32ucrt/sys-root/mingw/include/c++/x86_64-w64-mingw32ucrt
651*12c85518Srobert // /usr/x86_64-w64-mingw32ucrt/sys-root/mingw/include/c++/backward
652*12c85518Srobert // /usr/x86_64-w64-mingw32ucrt/sys-root/mingw/include
653*12c85518Srobert // /usr/lib/gcc/x86_64-w64-mingw32ucrt/12.2.1/include-fixed
654*12c85518Srobert 
AddClangSystemIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const655e5dd7070Spatrick void toolchains::MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
656e5dd7070Spatrick                                                   ArgStringList &CC1Args) const {
657e5dd7070Spatrick   if (DriverArgs.hasArg(options::OPT_nostdinc))
658e5dd7070Spatrick     return;
659e5dd7070Spatrick 
660e5dd7070Spatrick   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
661e5dd7070Spatrick     SmallString<1024> P(getDriver().ResourceDir);
662e5dd7070Spatrick     llvm::sys::path::append(P, "include");
663e5dd7070Spatrick     addSystemInclude(DriverArgs, CC1Args, P.str());
664e5dd7070Spatrick   }
665e5dd7070Spatrick 
666e5dd7070Spatrick   if (DriverArgs.hasArg(options::OPT_nostdlibinc))
667e5dd7070Spatrick     return;
668e5dd7070Spatrick 
669e5dd7070Spatrick   addSystemInclude(DriverArgs, CC1Args,
670*12c85518Srobert                    Base + SubdirName + llvm::sys::path::get_separator() +
671*12c85518Srobert                        "include");
672*12c85518Srobert 
673*12c85518Srobert   // Gentoo
674*12c85518Srobert   addSystemInclude(DriverArgs, CC1Args,
675*12c85518Srobert                    Base + SubdirName + llvm::sys::path::get_separator() + "usr/include");
676*12c85518Srobert 
677*12c85518Srobert   // Only include <base>/include if we're not cross compiling (but do allow it
678*12c85518Srobert   // if we're on Windows and building for Windows on another architecture),
679*12c85518Srobert   // or if the sysroot has been set (where we presume the user has pointed it
680*12c85518Srobert   // at an arch specific subdirectory).
681*12c85518Srobert   if (!::isCrossCompiling(getTriple(), /*RequireArchMatch=*/false) ||
682*12c85518Srobert       getDriver().SysRoot.size())
683*12c85518Srobert     addSystemInclude(DriverArgs, CC1Args, Base + "include");
684e5dd7070Spatrick }
685e5dd7070Spatrick 
addClangTargetOptions(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args,Action::OffloadKind DeviceOffloadKind) const686*12c85518Srobert void toolchains::MinGW::addClangTargetOptions(
687*12c85518Srobert     const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
688*12c85518Srobert     Action::OffloadKind DeviceOffloadKind) const {
689*12c85518Srobert   if (Arg *A = DriverArgs.getLastArg(options::OPT_mguard_EQ)) {
690*12c85518Srobert     StringRef GuardArgs = A->getValue();
691*12c85518Srobert     if (GuardArgs == "none") {
692*12c85518Srobert       // Do nothing.
693*12c85518Srobert     } else if (GuardArgs == "cf") {
694*12c85518Srobert       // Emit CFG instrumentation and the table of address-taken functions.
695*12c85518Srobert       CC1Args.push_back("-cfguard");
696*12c85518Srobert     } else if (GuardArgs == "cf-nochecks") {
697*12c85518Srobert       // Emit only the table of address-taken functions.
698*12c85518Srobert       CC1Args.push_back("-cfguard-no-checks");
699*12c85518Srobert     } else {
700*12c85518Srobert       getDriver().Diag(diag::err_drv_unsupported_option_argument)
701*12c85518Srobert           << A->getSpelling() << GuardArgs;
702*12c85518Srobert     }
703*12c85518Srobert   }
704e5dd7070Spatrick }
705e5dd7070Spatrick 
AddClangCXXStdlibIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const706e5dd7070Spatrick void toolchains::MinGW::AddClangCXXStdlibIncludeArgs(
707e5dd7070Spatrick     const ArgList &DriverArgs, ArgStringList &CC1Args) const {
708*12c85518Srobert   if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc,
709*12c85518Srobert                         options::OPT_nostdincxx))
710e5dd7070Spatrick     return;
711e5dd7070Spatrick 
712e5dd7070Spatrick   StringRef Slash = llvm::sys::path::get_separator();
713e5dd7070Spatrick 
714e5dd7070Spatrick   switch (GetCXXStdlibType(DriverArgs)) {
715*12c85518Srobert   case ToolChain::CST_Libcxx: {
716*12c85518Srobert     std::string TargetDir = (Base + "include" + Slash + getTripleString() +
717*12c85518Srobert                              Slash + "c++" + Slash + "v1")
718*12c85518Srobert                                 .str();
719*12c85518Srobert     if (getDriver().getVFS().exists(TargetDir))
720*12c85518Srobert       addSystemInclude(DriverArgs, CC1Args, TargetDir);
721*12c85518Srobert     addSystemInclude(DriverArgs, CC1Args,
722*12c85518Srobert                      Base + SubdirName + Slash + "include" + Slash + "c++" +
723*12c85518Srobert                          Slash + "v1");
724e5dd7070Spatrick     addSystemInclude(DriverArgs, CC1Args,
725e5dd7070Spatrick                      Base + "include" + Slash + "c++" + Slash + "v1");
726e5dd7070Spatrick     break;
727*12c85518Srobert   }
728e5dd7070Spatrick 
729e5dd7070Spatrick   case ToolChain::CST_Libstdcxx:
730*12c85518Srobert     llvm::SmallVector<llvm::SmallString<1024>, 7> CppIncludeBases;
731e5dd7070Spatrick     CppIncludeBases.emplace_back(Base);
732*12c85518Srobert     llvm::sys::path::append(CppIncludeBases[0], SubdirName, "include", "c++");
733e5dd7070Spatrick     CppIncludeBases.emplace_back(Base);
734*12c85518Srobert     llvm::sys::path::append(CppIncludeBases[1], SubdirName, "include", "c++",
735*12c85518Srobert                             Ver);
736e5dd7070Spatrick     CppIncludeBases.emplace_back(Base);
737e5dd7070Spatrick     llvm::sys::path::append(CppIncludeBases[2], "include", "c++", Ver);
738e5dd7070Spatrick     CppIncludeBases.emplace_back(GccLibDir);
739e5dd7070Spatrick     llvm::sys::path::append(CppIncludeBases[3], "include", "c++");
740*12c85518Srobert     CppIncludeBases.emplace_back(GccLibDir);
741*12c85518Srobert     llvm::sys::path::append(CppIncludeBases[4], "include",
742*12c85518Srobert                             "g++-v" + GccVer.Text);
743*12c85518Srobert     CppIncludeBases.emplace_back(GccLibDir);
744*12c85518Srobert     llvm::sys::path::append(CppIncludeBases[5], "include",
745*12c85518Srobert                             "g++-v" + GccVer.MajorStr + "." + GccVer.MinorStr);
746*12c85518Srobert     CppIncludeBases.emplace_back(GccLibDir);
747*12c85518Srobert     llvm::sys::path::append(CppIncludeBases[6], "include",
748*12c85518Srobert                             "g++-v" + GccVer.MajorStr);
749e5dd7070Spatrick     for (auto &CppIncludeBase : CppIncludeBases) {
750e5dd7070Spatrick       addSystemInclude(DriverArgs, CC1Args, CppIncludeBase);
751e5dd7070Spatrick       CppIncludeBase += Slash;
752*12c85518Srobert       addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + TripleDirName);
753e5dd7070Spatrick       addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + "backward");
754e5dd7070Spatrick     }
755e5dd7070Spatrick     break;
756e5dd7070Spatrick   }
757e5dd7070Spatrick }
758*12c85518Srobert 
testTriple(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)759*12c85518Srobert static bool testTriple(const Driver &D, const llvm::Triple &Triple,
760*12c85518Srobert                        const ArgList &Args) {
761*12c85518Srobert   // If an explicit sysroot is set, that will be used and we shouldn't try to
762*12c85518Srobert   // detect anything else.
763*12c85518Srobert   std::string SubdirName;
764*12c85518Srobert   if (D.SysRoot.size())
765*12c85518Srobert     return true;
766*12c85518Srobert   llvm::Triple LiteralTriple = getLiteralTriple(D, Triple);
767*12c85518Srobert   if (llvm::ErrorOr<std::string> TargetSubdir =
768*12c85518Srobert           findClangRelativeSysroot(D, LiteralTriple, Triple, SubdirName))
769*12c85518Srobert     return true;
770*12c85518Srobert   if (llvm::ErrorOr<std::string> GPPName = findGcc(LiteralTriple, Triple))
771*12c85518Srobert     return true;
772*12c85518Srobert   // If we neither found a colocated sysroot or a matching gcc executable,
773*12c85518Srobert   // conclude that we can't know if this is the correct spelling of the triple.
774*12c85518Srobert   return false;
775*12c85518Srobert }
776*12c85518Srobert 
adjustTriple(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)777*12c85518Srobert static llvm::Triple adjustTriple(const Driver &D, const llvm::Triple &Triple,
778*12c85518Srobert                                  const ArgList &Args) {
779*12c85518Srobert   // First test if the original triple can find a sysroot with the triple
780*12c85518Srobert   // name.
781*12c85518Srobert   if (testTriple(D, Triple, Args))
782*12c85518Srobert     return Triple;
783*12c85518Srobert   llvm::SmallVector<llvm::StringRef, 3> Archs;
784*12c85518Srobert   // If not, test a couple other possible arch names that might be what was
785*12c85518Srobert   // intended.
786*12c85518Srobert   if (Triple.getArch() == llvm::Triple::x86) {
787*12c85518Srobert     Archs.emplace_back("i386");
788*12c85518Srobert     Archs.emplace_back("i586");
789*12c85518Srobert     Archs.emplace_back("i686");
790*12c85518Srobert   } else if (Triple.getArch() == llvm::Triple::arm ||
791*12c85518Srobert              Triple.getArch() == llvm::Triple::thumb) {
792*12c85518Srobert     Archs.emplace_back("armv7");
793*12c85518Srobert   }
794*12c85518Srobert   for (auto A : Archs) {
795*12c85518Srobert     llvm::Triple TestTriple(Triple);
796*12c85518Srobert     TestTriple.setArchName(A);
797*12c85518Srobert     if (testTriple(D, TestTriple, Args))
798*12c85518Srobert       return TestTriple;
799*12c85518Srobert   }
800*12c85518Srobert   // If none was found, just proceed with the original value.
801*12c85518Srobert   return Triple;
802*12c85518Srobert }
803*12c85518Srobert 
fixTripleArch(const Driver & D,llvm::Triple & Triple,const ArgList & Args)804*12c85518Srobert void toolchains::MinGW::fixTripleArch(const Driver &D, llvm::Triple &Triple,
805*12c85518Srobert                                       const ArgList &Args) {
806*12c85518Srobert   if (Triple.getArch() == llvm::Triple::x86 ||
807*12c85518Srobert       Triple.getArch() == llvm::Triple::arm ||
808*12c85518Srobert       Triple.getArch() == llvm::Triple::thumb)
809*12c85518Srobert     Triple = adjustTriple(D, Triple, Args);
810*12c85518Srobert }
811