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