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