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).starts_with("msvcr") || 90 StringRef(Lib).starts_with("ucrt") || 91 StringRef(Lib).starts_with("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 D.Diag(diag::err_target_unknown_triple) << TC.getEffectiveTriple().str(); 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 (!Args.hasFlag(options::OPT_fauto_import, options::OPT_fno_auto_import, 173 true)) 174 CmdArgs.push_back("--disable-auto-import"); 175 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"); 182 else 183 D.Diag(diag::err_drv_unsupported_option_argument) 184 << A->getSpelling() << GuardArgs; 185 } 186 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(); 196 } else 197 CmdArgs.push_back(OutputFile); 198 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); 204 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. 211 CmdArgs.push_back( 212 TC.getCompilerRTArgString(Args, "asan_dynamic", ToolChain::FT_Shared)); 213 } 214 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"))); 218 } else { 219 if (Args.hasArg(options::OPT_municode)) 220 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2u.o"))); 221 else 222 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2.o"))); 223 } 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"))); 227 } 228 229 Args.AddAllArgs(CmdArgs, options::OPT_L); 230 TC.AddFilePathLibArgs(Args, CmdArgs); 231 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)); 237 } 238 auto CRTPath = TC.getCompilerRTPath(); 239 if (TC.getVFS().exists(CRTPath)) 240 CmdArgs.push_back(Args.MakeArgString("-L" + CRTPath)); 241 242 AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); 243 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); 248 } 249 250 if (C.getDriver().IsFlangMode()) { 251 addFortranRuntimeLibraryPath(TC, Args, CmdArgs); 252 addFortranRuntimeLibs(TC, Args, CmdArgs); 253 } 254 255 // TODO: Add profile stuff here 256 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"); 265 } 266 267 bool HasWindowsApp = false; 268 for (auto Lib : Args.getAllArgValues(options::OPT_l)) { 269 if (Lib == "windowsapp") { 270 HasWindowsApp = true; 271 break; 272 } 273 } 274 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"); 279 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"); 285 } 286 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"); 292 break; 293 case Driver::OMPRT_IOMP5: 294 CmdArgs.push_back("-liomp5md"); 295 break; 296 case Driver::OMPRT_GOMP: 297 CmdArgs.push_back("-lgomp"); 298 break; 299 case Driver::OMPRT_Unknown: 300 // Already diagnosed. 301 break; 302 } 303 } 304 305 AddLibGCC(Args, CmdArgs); 306 307 if (Args.hasArg(options::OPT_pg)) 308 CmdArgs.push_back("-lgmon"); 309 310 if (Args.hasArg(options::OPT_pthread)) 311 CmdArgs.push_back("-lpthread"); 312 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)); 317 CmdArgs.push_back( 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 324 // runtime thunk. 325 CmdArgs.push_back("--whole-archive"); 326 CmdArgs.push_back( 327 TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); 328 CmdArgs.push_back("--no-whole-archive"); 329 } 330 331 TC.addProfileRTLibs(Args, CmdArgs); 332 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"); 340 } 341 CmdArgs.push_back("-ladvapi32"); 342 CmdArgs.push_back("-lshell32"); 343 CmdArgs.push_back("-luser32"); 344 CmdArgs.push_back("-lkernel32"); 345 } 346 347 if (Args.hasArg(options::OPT_static)) { 348 CmdArgs.push_back("--end-group"); 349 } else { 350 AddLibGCC(Args, CmdArgs); 351 if (!HasWindowsApp) 352 CmdArgs.push_back("-lkernel32"); 353 } 354 } 355 356 if (!Args.hasArg(options::OPT_nostartfiles)) { 357 // Add crtfastmath.o if available and fast math is enabled. 358 TC.addFastMathRuntimeIfAvailable(Args, CmdArgs); 359 360 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o"))); 361 } 362 } 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)); 367 } 368 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) 372 return true; 373 if (RequireArchMatch && HostTriple.getArch() != T.getArch()) 374 return true; 375 return false; 376 } 377 378 // Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple. 379 static bool findGccVersion(StringRef LibDir, std::string &GccLibDir, 380 std::string &Ver, 381 toolchains::Generic_GCC::GCCVersion &Version) { 382 Version = toolchains::Generic_GCC::GCCVersion::Parse("0.0.0"); 383 std::error_code EC; 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) 390 continue; 391 if (CandidateVersion <= Version) 392 continue; 393 Version = CandidateVersion; 394 Ver = std::string(VersionText); 395 GccLibDir = LI->path(); 396 } 397 return Ver.size(); 398 } 399 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; 405 } 406 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"; 419 } 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); 428 return; 429 } 430 } 431 } 432 } 433 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)) 449 return GPPName; 450 return make_error_code(std::errc::no_such_file_or_directory); 451 } 452 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(); 469 } 470 } 471 return make_error_code(std::errc::no_such_file_or_directory); 472 } 473 474 static bool looksLikeMinGWSysroot(const std::string &Directory) { 475 StringRef Sep = llvm::sys::path::get_separator(); 476 if (!llvm::sys::fs::exists(Directory + Sep + "include" + Sep + "_mingw.h")) 477 return false; 478 if (!llvm::sys::fs::exists(Directory + Sep + "lib" + Sep + "libkernel32.a")) 479 return false; 480 return true; 481 } 482 483 toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, 484 const ArgList &Args) 485 : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args), 486 RocmInstallation(D, Triple, Args) { 487 getProgramPaths().push_back(getDriver().getInstalledDir()); 488 489 std::string InstallBase = 490 std::string(llvm::sys::path::parent_path(getDriver().getInstalledDir())); 491 // The sequence for detecting a sysroot here should be kept in sync with 492 // the testTriple function below. 493 llvm::Triple LiteralTriple = getLiteralTriple(D, getTriple()); 494 if (getDriver().SysRoot.size()) 495 Base = getDriver().SysRoot; 496 // Look for <clang-bin>/../<triplet>; if found, use <clang-bin>/.. as the 497 // base as it could still be a base for a gcc setup with libgcc. 498 else if (llvm::ErrorOr<std::string> TargetSubdir = findClangRelativeSysroot( 499 getDriver(), LiteralTriple, getTriple(), SubdirName)) 500 Base = std::string(llvm::sys::path::parent_path(TargetSubdir.get())); 501 // If the install base of Clang seems to have mingw sysroot files directly 502 // in the toplevel include and lib directories, use this as base instead of 503 // looking for a triple prefixed GCC in the path. 504 else if (looksLikeMinGWSysroot(InstallBase)) 505 Base = InstallBase; 506 else if (llvm::ErrorOr<std::string> GPPName = 507 findGcc(LiteralTriple, getTriple())) 508 Base = std::string(llvm::sys::path::parent_path( 509 llvm::sys::path::parent_path(GPPName.get()))); 510 else 511 Base = InstallBase; 512 513 Base += llvm::sys::path::get_separator(); 514 findGccLibDir(LiteralTriple); 515 TripleDirName = SubdirName; 516 // GccLibDir must precede Base/lib so that the 517 // correct crtbegin.o ,cetend.o would be found. 518 getFilePaths().push_back(GccLibDir); 519 520 // openSUSE/Fedora 521 std::string CandidateSubdir = SubdirName + "/sys-root/mingw"; 522 if (getDriver().getVFS().exists(Base + CandidateSubdir)) 523 SubdirName = CandidateSubdir; 524 525 getFilePaths().push_back( 526 (Base + SubdirName + llvm::sys::path::get_separator() + "lib").str()); 527 528 // Gentoo 529 getFilePaths().push_back( 530 (Base + SubdirName + llvm::sys::path::get_separator() + "mingw/lib").str()); 531 532 // Only include <base>/lib if we're not cross compiling (not even for 533 // windows->windows to a different arch), or if the sysroot has been set 534 // (where we presume the user has pointed it at an arch specific 535 // subdirectory). 536 if (!::isCrossCompiling(getTriple(), /*RequireArchMatch=*/true) || 537 getDriver().SysRoot.size()) 538 getFilePaths().push_back(Base + "lib"); 539 540 NativeLLVMSupport = 541 Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER) 542 .equals_insensitive("lld"); 543 } 544 545 Tool *toolchains::MinGW::getTool(Action::ActionClass AC) const { 546 switch (AC) { 547 case Action::PreprocessJobClass: 548 if (!Preprocessor) 549 Preprocessor.reset(new tools::gcc::Preprocessor(*this)); 550 return Preprocessor.get(); 551 case Action::CompileJobClass: 552 if (!Compiler) 553 Compiler.reset(new tools::gcc::Compiler(*this)); 554 return Compiler.get(); 555 default: 556 return ToolChain::getTool(AC); 557 } 558 } 559 560 Tool *toolchains::MinGW::buildAssembler() const { 561 return new tools::MinGW::Assembler(*this); 562 } 563 564 Tool *toolchains::MinGW::buildLinker() const { 565 return new tools::MinGW::Linker(*this); 566 } 567 568 bool toolchains::MinGW::HasNativeLLVMSupport() const { 569 return NativeLLVMSupport; 570 } 571 572 ToolChain::UnwindTableLevel 573 toolchains::MinGW::getDefaultUnwindTableLevel(const ArgList &Args) const { 574 Arg *ExceptionArg = Args.getLastArg(options::OPT_fsjlj_exceptions, 575 options::OPT_fseh_exceptions, 576 options::OPT_fdwarf_exceptions); 577 if (ExceptionArg && 578 ExceptionArg->getOption().matches(options::OPT_fseh_exceptions)) 579 return UnwindTableLevel::Asynchronous; 580 581 if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::arm || 582 getArch() == llvm::Triple::thumb || getArch() == llvm::Triple::aarch64) 583 return UnwindTableLevel::Asynchronous; 584 return UnwindTableLevel::None; 585 } 586 587 bool toolchains::MinGW::isPICDefault() const { 588 return getArch() == llvm::Triple::x86_64 || 589 getArch() == llvm::Triple::aarch64; 590 } 591 592 bool toolchains::MinGW::isPIEDefault(const llvm::opt::ArgList &Args) const { 593 return false; 594 } 595 596 bool toolchains::MinGW::isPICDefaultForced() const { return true; } 597 598 llvm::ExceptionHandling 599 toolchains::MinGW::GetExceptionModel(const ArgList &Args) const { 600 if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::aarch64 || 601 getArch() == llvm::Triple::arm || getArch() == llvm::Triple::thumb) 602 return llvm::ExceptionHandling::WinEH; 603 return llvm::ExceptionHandling::DwarfCFI; 604 } 605 606 SanitizerMask toolchains::MinGW::getSupportedSanitizers() const { 607 SanitizerMask Res = ToolChain::getSupportedSanitizers(); 608 Res |= SanitizerKind::Address; 609 Res |= SanitizerKind::PointerCompare; 610 Res |= SanitizerKind::PointerSubtract; 611 Res |= SanitizerKind::Vptr; 612 return Res; 613 } 614 615 void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs, 616 ArgStringList &CC1Args) const { 617 CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args); 618 } 619 620 void toolchains::MinGW::AddHIPIncludeArgs(const ArgList &DriverArgs, 621 ArgStringList &CC1Args) const { 622 RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args); 623 } 624 625 void toolchains::MinGW::printVerboseInfo(raw_ostream &OS) const { 626 CudaInstallation.print(OS); 627 RocmInstallation.print(OS); 628 } 629 630 // Include directories for various hosts: 631 632 // Windows, mingw.org 633 // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++ 634 // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\mingw32 635 // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\backward 636 // c:\mingw\include 637 // c:\mingw\mingw32\include 638 639 // Windows, mingw-w64 mingw-builds 640 // c:\mingw32\i686-w64-mingw32\include 641 // c:\mingw32\i686-w64-mingw32\include\c++ 642 // c:\mingw32\i686-w64-mingw32\include\c++\i686-w64-mingw32 643 // c:\mingw32\i686-w64-mingw32\include\c++\backward 644 645 // Windows, mingw-w64 msys2 646 // c:\msys64\mingw32\include 647 // c:\msys64\mingw32\i686-w64-mingw32\include 648 // c:\msys64\mingw32\include\c++\4.9.2 649 // c:\msys64\mingw32\include\c++\4.9.2\i686-w64-mingw32 650 // c:\msys64\mingw32\include\c++\4.9.2\backward 651 652 // openSUSE 653 // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++ 654 // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/x86_64-w64-mingw32 655 // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/backward 656 // /usr/x86_64-w64-mingw32/sys-root/mingw/include 657 658 // Arch Linux 659 // /usr/i686-w64-mingw32/include/c++/5.1.0 660 // /usr/i686-w64-mingw32/include/c++/5.1.0/i686-w64-mingw32 661 // /usr/i686-w64-mingw32/include/c++/5.1.0/backward 662 // /usr/i686-w64-mingw32/include 663 664 // Ubuntu 665 // /usr/include/c++/4.8 666 // /usr/include/c++/4.8/x86_64-w64-mingw32 667 // /usr/include/c++/4.8/backward 668 // /usr/x86_64-w64-mingw32/include 669 670 // Fedora 671 // /usr/x86_64-w64-mingw32ucrt/sys-root/mingw/include/c++/x86_64-w64-mingw32ucrt 672 // /usr/x86_64-w64-mingw32ucrt/sys-root/mingw/include/c++/backward 673 // /usr/x86_64-w64-mingw32ucrt/sys-root/mingw/include 674 // /usr/lib/gcc/x86_64-w64-mingw32ucrt/12.2.1/include-fixed 675 676 void toolchains::MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 677 ArgStringList &CC1Args) const { 678 if (DriverArgs.hasArg(options::OPT_nostdinc)) 679 return; 680 681 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 682 SmallString<1024> P(getDriver().ResourceDir); 683 llvm::sys::path::append(P, "include"); 684 addSystemInclude(DriverArgs, CC1Args, P.str()); 685 } 686 687 if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 688 return; 689 690 addSystemInclude(DriverArgs, CC1Args, 691 Base + SubdirName + llvm::sys::path::get_separator() + 692 "include"); 693 694 // Gentoo 695 addSystemInclude(DriverArgs, CC1Args, 696 Base + SubdirName + llvm::sys::path::get_separator() + "usr/include"); 697 698 // Only include <base>/include if we're not cross compiling (but do allow it 699 // if we're on Windows and building for Windows on another architecture), 700 // or if the sysroot has been set (where we presume the user has pointed it 701 // at an arch specific subdirectory). 702 if (!::isCrossCompiling(getTriple(), /*RequireArchMatch=*/false) || 703 getDriver().SysRoot.size()) 704 addSystemInclude(DriverArgs, CC1Args, Base + "include"); 705 } 706 707 void toolchains::MinGW::addClangTargetOptions( 708 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, 709 Action::OffloadKind DeviceOffloadKind) const { 710 if (Arg *A = DriverArgs.getLastArg(options::OPT_mguard_EQ)) { 711 StringRef GuardArgs = A->getValue(); 712 if (GuardArgs == "none") { 713 // Do nothing. 714 } else if (GuardArgs == "cf") { 715 // Emit CFG instrumentation and the table of address-taken functions. 716 CC1Args.push_back("-cfguard"); 717 } else if (GuardArgs == "cf-nochecks") { 718 // Emit only the table of address-taken functions. 719 CC1Args.push_back("-cfguard-no-checks"); 720 } else { 721 getDriver().Diag(diag::err_drv_unsupported_option_argument) 722 << A->getSpelling() << GuardArgs; 723 } 724 } 725 726 CC1Args.push_back("-fno-use-init-array"); 727 728 for (auto Opt : {options::OPT_mthreads, options::OPT_mwindows, 729 options::OPT_mconsole, options::OPT_mdll}) { 730 if (Arg *A = DriverArgs.getLastArgNoClaim(Opt)) 731 A->ignoreTargetSpecific(); 732 } 733 } 734 735 void toolchains::MinGW::AddClangCXXStdlibIncludeArgs( 736 const ArgList &DriverArgs, ArgStringList &CC1Args) const { 737 if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc, 738 options::OPT_nostdincxx)) 739 return; 740 741 StringRef Slash = llvm::sys::path::get_separator(); 742 743 switch (GetCXXStdlibType(DriverArgs)) { 744 case ToolChain::CST_Libcxx: { 745 std::string TargetDir = (Base + "include" + Slash + getTripleString() + 746 Slash + "c++" + Slash + "v1") 747 .str(); 748 if (getDriver().getVFS().exists(TargetDir)) 749 addSystemInclude(DriverArgs, CC1Args, TargetDir); 750 addSystemInclude(DriverArgs, CC1Args, 751 Base + SubdirName + Slash + "include" + Slash + "c++" + 752 Slash + "v1"); 753 addSystemInclude(DriverArgs, CC1Args, 754 Base + "include" + Slash + "c++" + Slash + "v1"); 755 break; 756 } 757 758 case ToolChain::CST_Libstdcxx: 759 llvm::SmallVector<llvm::SmallString<1024>, 7> CppIncludeBases; 760 CppIncludeBases.emplace_back(Base); 761 llvm::sys::path::append(CppIncludeBases[0], SubdirName, "include", "c++"); 762 CppIncludeBases.emplace_back(Base); 763 llvm::sys::path::append(CppIncludeBases[1], SubdirName, "include", "c++", 764 Ver); 765 CppIncludeBases.emplace_back(Base); 766 llvm::sys::path::append(CppIncludeBases[2], "include", "c++", Ver); 767 CppIncludeBases.emplace_back(GccLibDir); 768 llvm::sys::path::append(CppIncludeBases[3], "include", "c++"); 769 CppIncludeBases.emplace_back(GccLibDir); 770 llvm::sys::path::append(CppIncludeBases[4], "include", 771 "g++-v" + GccVer.Text); 772 CppIncludeBases.emplace_back(GccLibDir); 773 llvm::sys::path::append(CppIncludeBases[5], "include", 774 "g++-v" + GccVer.MajorStr + "." + GccVer.MinorStr); 775 CppIncludeBases.emplace_back(GccLibDir); 776 llvm::sys::path::append(CppIncludeBases[6], "include", 777 "g++-v" + GccVer.MajorStr); 778 for (auto &CppIncludeBase : CppIncludeBases) { 779 addSystemInclude(DriverArgs, CC1Args, CppIncludeBase); 780 CppIncludeBase += Slash; 781 addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + TripleDirName); 782 addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + "backward"); 783 } 784 break; 785 } 786 } 787 788 static bool testTriple(const Driver &D, const llvm::Triple &Triple, 789 const ArgList &Args) { 790 // If an explicit sysroot is set, that will be used and we shouldn't try to 791 // detect anything else. 792 std::string SubdirName; 793 if (D.SysRoot.size()) 794 return true; 795 llvm::Triple LiteralTriple = getLiteralTriple(D, Triple); 796 std::string InstallBase = 797 std::string(llvm::sys::path::parent_path(D.getInstalledDir())); 798 if (llvm::ErrorOr<std::string> TargetSubdir = 799 findClangRelativeSysroot(D, LiteralTriple, Triple, SubdirName)) 800 return true; 801 // If the install base itself looks like a mingw sysroot, we'll use that 802 // - don't use any potentially unrelated gcc to influence what triple to use. 803 if (looksLikeMinGWSysroot(InstallBase)) 804 return false; 805 if (llvm::ErrorOr<std::string> GPPName = findGcc(LiteralTriple, Triple)) 806 return true; 807 // If we neither found a colocated sysroot or a matching gcc executable, 808 // conclude that we can't know if this is the correct spelling of the triple. 809 return false; 810 } 811 812 static llvm::Triple adjustTriple(const Driver &D, const llvm::Triple &Triple, 813 const ArgList &Args) { 814 // First test if the original triple can find a sysroot with the triple 815 // name. 816 if (testTriple(D, Triple, Args)) 817 return Triple; 818 llvm::SmallVector<llvm::StringRef, 3> Archs; 819 // If not, test a couple other possible arch names that might be what was 820 // intended. 821 if (Triple.getArch() == llvm::Triple::x86) { 822 Archs.emplace_back("i386"); 823 Archs.emplace_back("i586"); 824 Archs.emplace_back("i686"); 825 } else if (Triple.getArch() == llvm::Triple::arm || 826 Triple.getArch() == llvm::Triple::thumb) { 827 Archs.emplace_back("armv7"); 828 } 829 for (auto A : Archs) { 830 llvm::Triple TestTriple(Triple); 831 TestTriple.setArchName(A); 832 if (testTriple(D, TestTriple, Args)) 833 return TestTriple; 834 } 835 // If none was found, just proceed with the original value. 836 return Triple; 837 } 838 839 void toolchains::MinGW::fixTripleArch(const Driver &D, llvm::Triple &Triple, 840 const ArgList &Args) { 841 if (Triple.getArch() == llvm::Triple::x86 || 842 Triple.getArch() == llvm::Triple::arm || 843 Triple.getArch() == llvm::Triple::thumb) 844 Triple = adjustTriple(D, Triple, Args); 845 } 846