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