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