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