1 //===-- MSVC.cpp - MSVC ToolChain Implementations -------------------------===// 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 "MSVC.h" 10 #include "CommonArgs.h" 11 #include "Darwin.h" 12 #include "clang/Basic/CharInfo.h" 13 #include "clang/Basic/Version.h" 14 #include "clang/Config/config.h" 15 #include "clang/Driver/Compilation.h" 16 #include "clang/Driver/Driver.h" 17 #include "clang/Driver/DriverDiagnostic.h" 18 #include "clang/Driver/Options.h" 19 #include "clang/Driver/SanitizerArgs.h" 20 #include "llvm/ADT/StringExtras.h" 21 #include "llvm/Option/Arg.h" 22 #include "llvm/Option/ArgList.h" 23 #include "llvm/Support/ConvertUTF.h" 24 #include "llvm/Support/ErrorHandling.h" 25 #include "llvm/Support/FileSystem.h" 26 #include "llvm/Support/MemoryBuffer.h" 27 #include "llvm/Support/Path.h" 28 #include "llvm/Support/Process.h" 29 #include "llvm/Support/VirtualFileSystem.h" 30 #include "llvm/TargetParser/Host.h" 31 #include <cstdio> 32 33 #ifdef _WIN32 34 #define WIN32_LEAN_AND_MEAN 35 #define NOGDI 36 #ifndef NOMINMAX 37 #define NOMINMAX 38 #endif 39 #include <windows.h> 40 #endif 41 42 using namespace clang::driver; 43 using namespace clang::driver::toolchains; 44 using namespace clang::driver::tools; 45 using namespace clang; 46 using namespace llvm::opt; 47 48 static bool canExecute(llvm::vfs::FileSystem &VFS, StringRef Path) { 49 auto Status = VFS.status(Path); 50 if (!Status) 51 return false; 52 return (Status->getPermissions() & llvm::sys::fs::perms::all_exe) != 0; 53 } 54 55 // Try to find Exe from a Visual Studio distribution. This first tries to find 56 // an installed copy of Visual Studio and, failing that, looks in the PATH, 57 // making sure that whatever executable that's found is not a same-named exe 58 // from clang itself to prevent clang from falling back to itself. 59 static std::string FindVisualStudioExecutable(const ToolChain &TC, 60 const char *Exe) { 61 const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC); 62 SmallString<128> FilePath( 63 MSVC.getSubDirectoryPath(llvm::SubDirectoryType::Bin)); 64 llvm::sys::path::append(FilePath, Exe); 65 return std::string(canExecute(TC.getVFS(), FilePath) ? FilePath.str() : Exe); 66 } 67 68 void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, 69 const InputInfo &Output, 70 const InputInfoList &Inputs, 71 const ArgList &Args, 72 const char *LinkingOutput) const { 73 ArgStringList CmdArgs; 74 75 auto &TC = static_cast<const toolchains::MSVCToolChain &>(getToolChain()); 76 77 assert((Output.isFilename() || Output.isNothing()) && "invalid output"); 78 if (Output.isFilename()) 79 CmdArgs.push_back( 80 Args.MakeArgString(std::string("-out:") + Output.getFilename())); 81 82 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) && 83 !C.getDriver().IsCLMode() && !C.getDriver().IsFlangMode()) { 84 CmdArgs.push_back("-defaultlib:libcmt"); 85 CmdArgs.push_back("-defaultlib:oldnames"); 86 } 87 88 // If the VC environment hasn't been configured (perhaps because the user 89 // did not run vcvarsall), try to build a consistent link environment. If 90 // the environment variable is set however, assume the user knows what 91 // they're doing. If the user passes /vctoolsdir or /winsdkdir, trust that 92 // over env vars. 93 if (const Arg *A = Args.getLastArg(options::OPT__SLASH_diasdkdir, 94 options::OPT__SLASH_winsysroot)) { 95 // cl.exe doesn't find the DIA SDK automatically, so this too requires 96 // explicit flags and doesn't automatically look in "DIA SDK" relative 97 // to the path we found for VCToolChainPath. 98 llvm::SmallString<128> DIAPath(A->getValue()); 99 if (A->getOption().getID() == options::OPT__SLASH_winsysroot) 100 llvm::sys::path::append(DIAPath, "DIA SDK"); 101 102 // The DIA SDK always uses the legacy vc arch, even in new MSVC versions. 103 llvm::sys::path::append(DIAPath, "lib", 104 llvm::archToLegacyVCArch(TC.getArch())); 105 CmdArgs.push_back(Args.MakeArgString(Twine("-libpath:") + DIAPath)); 106 } 107 if (!llvm::sys::Process::GetEnv("LIB") || 108 Args.getLastArg(options::OPT__SLASH_vctoolsdir, 109 options::OPT__SLASH_winsysroot)) { 110 CmdArgs.push_back(Args.MakeArgString( 111 Twine("-libpath:") + 112 TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib))); 113 CmdArgs.push_back(Args.MakeArgString( 114 Twine("-libpath:") + 115 TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib, "atlmfc"))); 116 } 117 if (!llvm::sys::Process::GetEnv("LIB") || 118 Args.getLastArg(options::OPT__SLASH_winsdkdir, 119 options::OPT__SLASH_winsysroot)) { 120 if (TC.useUniversalCRT()) { 121 std::string UniversalCRTLibPath; 122 if (TC.getUniversalCRTLibraryPath(Args, UniversalCRTLibPath)) 123 CmdArgs.push_back( 124 Args.MakeArgString(Twine("-libpath:") + UniversalCRTLibPath)); 125 } 126 std::string WindowsSdkLibPath; 127 if (TC.getWindowsSDKLibraryPath(Args, WindowsSdkLibPath)) 128 CmdArgs.push_back( 129 Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath)); 130 } 131 132 if (C.getDriver().IsFlangMode()) { 133 addFortranRuntimeLibraryPath(TC, Args, CmdArgs); 134 addFortranRuntimeLibs(TC, Args, CmdArgs); 135 136 // Inform the MSVC linker that we're generating a console application, i.e. 137 // one with `main` as the "user-defined" entry point. The `main` function is 138 // defined in flang's runtime libraries. 139 CmdArgs.push_back("/subsystem:console"); 140 } 141 142 // Add the compiler-rt library directories to libpath if they exist to help 143 // the linker find the various sanitizer, builtin, and profiling runtimes. 144 for (const auto &LibPath : TC.getLibraryPaths()) { 145 if (TC.getVFS().exists(LibPath)) 146 CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath)); 147 } 148 auto CRTPath = TC.getCompilerRTPath(); 149 if (TC.getVFS().exists(CRTPath)) 150 CmdArgs.push_back(Args.MakeArgString("-libpath:" + CRTPath)); 151 152 if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L)) 153 for (const auto &LibPath : Args.getAllArgValues(options::OPT_L)) 154 CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath)); 155 156 CmdArgs.push_back("-nologo"); 157 158 if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7)) 159 CmdArgs.push_back("-debug"); 160 161 // If we specify /hotpatch, let the linker add padding in front of each 162 // function, like MSVC does. 163 if (Args.hasArg(options::OPT_fms_hotpatch, options::OPT__SLASH_hotpatch)) 164 CmdArgs.push_back("-functionpadmin"); 165 166 // Pass on /Brepro if it was passed to the compiler. 167 // Note that /Brepro maps to -mno-incremental-linker-compatible. 168 bool DefaultIncrementalLinkerCompatible = 169 C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment(); 170 if (!Args.hasFlag(options::OPT_mincremental_linker_compatible, 171 options::OPT_mno_incremental_linker_compatible, 172 DefaultIncrementalLinkerCompatible)) 173 CmdArgs.push_back("-Brepro"); 174 175 bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd, 176 options::OPT_shared); 177 if (DLL) { 178 CmdArgs.push_back(Args.MakeArgString("-dll")); 179 180 SmallString<128> ImplibName(Output.getFilename()); 181 llvm::sys::path::replace_extension(ImplibName, "lib"); 182 CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName)); 183 } 184 185 if (TC.getSanitizerArgs(Args).needsFuzzer()) { 186 if (!Args.hasArg(options::OPT_shared)) 187 CmdArgs.push_back( 188 Args.MakeArgString(std::string("-wholearchive:") + 189 TC.getCompilerRTArgString(Args, "fuzzer"))); 190 CmdArgs.push_back(Args.MakeArgString("-debug")); 191 // Prevent the linker from padding sections we use for instrumentation 192 // arrays. 193 CmdArgs.push_back(Args.MakeArgString("-incremental:no")); 194 } 195 196 if (TC.getSanitizerArgs(Args).needsAsanRt()) { 197 CmdArgs.push_back(Args.MakeArgString("-debug")); 198 CmdArgs.push_back(Args.MakeArgString("-incremental:no")); 199 if (TC.getSanitizerArgs(Args).needsSharedRt() || 200 Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) { 201 for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"}) 202 CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib)); 203 // Make sure the dynamic runtime thunk is not optimized out at link time 204 // to ensure proper SEH handling. 205 CmdArgs.push_back(Args.MakeArgString( 206 TC.getArch() == llvm::Triple::x86 207 ? "-include:___asan_seh_interceptor" 208 : "-include:__asan_seh_interceptor")); 209 // Make sure the linker consider all object files from the dynamic runtime 210 // thunk. 211 CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") + 212 TC.getCompilerRT(Args, "asan_dynamic_runtime_thunk"))); 213 } else if (DLL) { 214 CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk")); 215 } else { 216 for (const auto &Lib : {"asan", "asan_cxx"}) { 217 CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib)); 218 // Make sure the linker consider all object files from the static lib. 219 // This is necessary because instrumented dlls need access to all the 220 // interface exported by the static lib in the main executable. 221 CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") + 222 TC.getCompilerRT(Args, Lib))); 223 } 224 } 225 } 226 227 Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link); 228 229 // Control Flow Guard checks 230 for (const Arg *A : Args.filtered(options::OPT__SLASH_guard)) { 231 StringRef GuardArgs = A->getValue(); 232 if (GuardArgs.equals_insensitive("cf") || 233 GuardArgs.equals_insensitive("cf,nochecks")) { 234 // MSVC doesn't yet support the "nochecks" modifier. 235 CmdArgs.push_back("-guard:cf"); 236 } else if (GuardArgs.equals_insensitive("cf-")) { 237 CmdArgs.push_back("-guard:cf-"); 238 } else if (GuardArgs.equals_insensitive("ehcont")) { 239 CmdArgs.push_back("-guard:ehcont"); 240 } else if (GuardArgs.equals_insensitive("ehcont-")) { 241 CmdArgs.push_back("-guard:ehcont-"); 242 } 243 } 244 245 if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, 246 options::OPT_fno_openmp, false)) { 247 CmdArgs.push_back("-nodefaultlib:vcomp.lib"); 248 CmdArgs.push_back("-nodefaultlib:vcompd.lib"); 249 CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") + 250 TC.getDriver().Dir + "/../lib")); 251 switch (TC.getDriver().getOpenMPRuntime(Args)) { 252 case Driver::OMPRT_OMP: 253 CmdArgs.push_back("-defaultlib:libomp.lib"); 254 break; 255 case Driver::OMPRT_IOMP5: 256 CmdArgs.push_back("-defaultlib:libiomp5md.lib"); 257 break; 258 case Driver::OMPRT_GOMP: 259 break; 260 case Driver::OMPRT_Unknown: 261 // Already diagnosed. 262 break; 263 } 264 } 265 266 // Add compiler-rt lib in case if it was explicitly 267 // specified as an argument for --rtlib option. 268 if (!Args.hasArg(options::OPT_nostdlib)) { 269 AddRunTimeLibs(TC, TC.getDriver(), CmdArgs, Args); 270 } 271 272 StringRef Linker = 273 Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER); 274 if (Linker.empty()) 275 Linker = "link"; 276 // We need to translate 'lld' into 'lld-link'. 277 else if (Linker.equals_insensitive("lld")) 278 Linker = "lld-link"; 279 280 if (Linker == "lld-link") { 281 for (Arg *A : Args.filtered(options::OPT_vfsoverlay)) 282 CmdArgs.push_back( 283 Args.MakeArgString(std::string("/vfsoverlay:") + A->getValue())); 284 285 if (C.getDriver().isUsingLTO() && 286 Args.hasFlag(options::OPT_gsplit_dwarf, options::OPT_gno_split_dwarf, 287 false)) 288 CmdArgs.push_back(Args.MakeArgString(Twine("/dwodir:") + 289 Output.getFilename() + "_dwo")); 290 } 291 292 // Add filenames, libraries, and other linker inputs. 293 for (const auto &Input : Inputs) { 294 if (Input.isFilename()) { 295 CmdArgs.push_back(Input.getFilename()); 296 continue; 297 } 298 299 const Arg &A = Input.getInputArg(); 300 301 // Render -l options differently for the MSVC linker. 302 if (A.getOption().matches(options::OPT_l)) { 303 StringRef Lib = A.getValue(); 304 const char *LinkLibArg; 305 if (Lib.ends_with(".lib")) 306 LinkLibArg = Args.MakeArgString(Lib); 307 else 308 LinkLibArg = Args.MakeArgString(Lib + ".lib"); 309 CmdArgs.push_back(LinkLibArg); 310 continue; 311 } 312 313 // Otherwise, this is some other kind of linker input option like -Wl, -z, 314 // or -L. Render it, even if MSVC doesn't understand it. 315 A.renderAsInput(Args, CmdArgs); 316 } 317 318 addHIPRuntimeLibArgs(TC, C, Args, CmdArgs); 319 320 TC.addProfileRTLibs(Args, CmdArgs); 321 322 std::vector<const char *> Environment; 323 324 // We need to special case some linker paths. In the case of the regular msvc 325 // linker, we need to use a special search algorithm. 326 llvm::SmallString<128> linkPath; 327 if (Linker.equals_insensitive("link")) { 328 // If we're using the MSVC linker, it's not sufficient to just use link 329 // from the program PATH, because other environments like GnuWin32 install 330 // their own link.exe which may come first. 331 linkPath = FindVisualStudioExecutable(TC, "link.exe"); 332 333 if (!TC.FoundMSVCInstall() && !canExecute(TC.getVFS(), linkPath)) { 334 llvm::SmallString<128> ClPath; 335 ClPath = TC.GetProgramPath("cl.exe"); 336 if (canExecute(TC.getVFS(), ClPath)) { 337 linkPath = llvm::sys::path::parent_path(ClPath); 338 llvm::sys::path::append(linkPath, "link.exe"); 339 if (!canExecute(TC.getVFS(), linkPath)) 340 C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found); 341 } else { 342 C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found); 343 } 344 } 345 346 // Clang handles passing the proper asan libs to the linker, which goes 347 // against link.exe's /INFERASANLIBS which automatically finds asan libs. 348 if (TC.getSanitizerArgs(Args).needsAsanRt()) 349 CmdArgs.push_back("/INFERASANLIBS:NO"); 350 351 #ifdef _WIN32 352 // When cross-compiling with VS2017 or newer, link.exe expects to have 353 // its containing bin directory at the top of PATH, followed by the 354 // native target bin directory. 355 // e.g. when compiling for x86 on an x64 host, PATH should start with: 356 // /bin/Hostx64/x86;/bin/Hostx64/x64 357 // This doesn't attempt to handle llvm::ToolsetLayout::DevDivInternal. 358 if (TC.getIsVS2017OrNewer() && 359 llvm::Triple(llvm::sys::getProcessTriple()).getArch() != TC.getArch()) { 360 auto HostArch = llvm::Triple(llvm::sys::getProcessTriple()).getArch(); 361 362 auto EnvBlockWide = 363 std::unique_ptr<wchar_t[], decltype(&FreeEnvironmentStringsW)>( 364 GetEnvironmentStringsW(), FreeEnvironmentStringsW); 365 if (!EnvBlockWide) 366 goto SkipSettingEnvironment; 367 368 size_t EnvCount = 0; 369 size_t EnvBlockLen = 0; 370 while (EnvBlockWide[EnvBlockLen] != L'\0') { 371 ++EnvCount; 372 EnvBlockLen += std::wcslen(&EnvBlockWide[EnvBlockLen]) + 373 1 /*string null-terminator*/; 374 } 375 ++EnvBlockLen; // add the block null-terminator 376 377 std::string EnvBlock; 378 if (!llvm::convertUTF16ToUTF8String( 379 llvm::ArrayRef<char>(reinterpret_cast<char *>(EnvBlockWide.get()), 380 EnvBlockLen * sizeof(EnvBlockWide[0])), 381 EnvBlock)) 382 goto SkipSettingEnvironment; 383 384 Environment.reserve(EnvCount); 385 386 // Now loop over each string in the block and copy them into the 387 // environment vector, adjusting the PATH variable as needed when we 388 // find it. 389 for (const char *Cursor = EnvBlock.data(); *Cursor != '\0';) { 390 llvm::StringRef EnvVar(Cursor); 391 if (EnvVar.starts_with_insensitive("path=")) { 392 constexpr size_t PrefixLen = 5; // strlen("path=") 393 Environment.push_back(Args.MakeArgString( 394 EnvVar.substr(0, PrefixLen) + 395 TC.getSubDirectoryPath(llvm::SubDirectoryType::Bin) + 396 llvm::Twine(llvm::sys::EnvPathSeparator) + 397 TC.getSubDirectoryPath(llvm::SubDirectoryType::Bin, HostArch) + 398 (EnvVar.size() > PrefixLen 399 ? llvm::Twine(llvm::sys::EnvPathSeparator) + 400 EnvVar.substr(PrefixLen) 401 : ""))); 402 } else { 403 Environment.push_back(Args.MakeArgString(EnvVar)); 404 } 405 Cursor += EnvVar.size() + 1 /*null-terminator*/; 406 } 407 } 408 SkipSettingEnvironment:; 409 #endif 410 } else { 411 linkPath = TC.GetProgramPath(Linker.str().c_str()); 412 } 413 414 auto LinkCmd = std::make_unique<Command>( 415 JA, *this, ResponseFileSupport::AtFileUTF16(), 416 Args.MakeArgString(linkPath), CmdArgs, Inputs, Output); 417 if (!Environment.empty()) 418 LinkCmd->setEnvironment(Environment); 419 C.addCommand(std::move(LinkCmd)); 420 } 421 422 MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple, 423 const ArgList &Args) 424 : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args), 425 RocmInstallation(D, Triple, Args) { 426 getProgramPaths().push_back(getDriver().getInstalledDir()); 427 if (getDriver().getInstalledDir() != getDriver().Dir) 428 getProgramPaths().push_back(getDriver().Dir); 429 430 std::optional<llvm::StringRef> VCToolsDir, VCToolsVersion; 431 if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir)) 432 VCToolsDir = A->getValue(); 433 if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsversion)) 434 VCToolsVersion = A->getValue(); 435 if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkdir)) 436 WinSdkDir = A->getValue(); 437 if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkversion)) 438 WinSdkVersion = A->getValue(); 439 if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsysroot)) 440 WinSysRoot = A->getValue(); 441 442 // Check the command line first, that's the user explicitly telling us what to 443 // use. Check the environment next, in case we're being invoked from a VS 444 // command prompt. Failing that, just try to find the newest Visual Studio 445 // version we can and use its default VC toolchain. 446 llvm::findVCToolChainViaCommandLine(getVFS(), VCToolsDir, VCToolsVersion, 447 WinSysRoot, VCToolChainPath, VSLayout) || 448 llvm::findVCToolChainViaEnvironment(getVFS(), VCToolChainPath, 449 VSLayout) || 450 llvm::findVCToolChainViaSetupConfig(getVFS(), VCToolsVersion, 451 VCToolChainPath, VSLayout) || 452 llvm::findVCToolChainViaRegistry(VCToolChainPath, VSLayout); 453 } 454 455 Tool *MSVCToolChain::buildLinker() const { 456 return new tools::visualstudio::Linker(*this); 457 } 458 459 Tool *MSVCToolChain::buildAssembler() const { 460 if (getTriple().isOSBinFormatMachO()) 461 return new tools::darwin::Assembler(*this); 462 getDriver().Diag(clang::diag::err_no_external_assembler); 463 return nullptr; 464 } 465 466 ToolChain::UnwindTableLevel 467 MSVCToolChain::getDefaultUnwindTableLevel(const ArgList &Args) const { 468 // Don't emit unwind tables by default for MachO targets. 469 if (getTriple().isOSBinFormatMachO()) 470 return UnwindTableLevel::None; 471 472 // All non-x86_32 Windows targets require unwind tables. However, LLVM 473 // doesn't know how to generate them for all targets, so only enable 474 // the ones that are actually implemented. 475 if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::arm || 476 getArch() == llvm::Triple::thumb || getArch() == llvm::Triple::aarch64) 477 return UnwindTableLevel::Asynchronous; 478 479 return UnwindTableLevel::None; 480 } 481 482 bool MSVCToolChain::isPICDefault() const { 483 return getArch() == llvm::Triple::x86_64 || 484 getArch() == llvm::Triple::aarch64; 485 } 486 487 bool MSVCToolChain::isPIEDefault(const llvm::opt::ArgList &Args) const { 488 return false; 489 } 490 491 bool MSVCToolChain::isPICDefaultForced() const { 492 return getArch() == llvm::Triple::x86_64 || 493 getArch() == llvm::Triple::aarch64; 494 } 495 496 void MSVCToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs, 497 ArgStringList &CC1Args) const { 498 CudaInstallation->AddCudaIncludeArgs(DriverArgs, CC1Args); 499 } 500 501 void MSVCToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs, 502 ArgStringList &CC1Args) const { 503 RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args); 504 } 505 506 void MSVCToolChain::AddHIPRuntimeLibArgs(const ArgList &Args, 507 ArgStringList &CmdArgs) const { 508 CmdArgs.append({Args.MakeArgString(StringRef("-libpath:") + 509 RocmInstallation->getLibPath()), 510 "amdhip64.lib"}); 511 } 512 513 void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const { 514 CudaInstallation->print(OS); 515 RocmInstallation->print(OS); 516 } 517 518 std::string 519 MSVCToolChain::getSubDirectoryPath(llvm::SubDirectoryType Type, 520 llvm::StringRef SubdirParent) const { 521 return llvm::getSubDirectoryPath(Type, VSLayout, VCToolChainPath, getArch(), 522 SubdirParent); 523 } 524 525 std::string 526 MSVCToolChain::getSubDirectoryPath(llvm::SubDirectoryType Type, 527 llvm::Triple::ArchType TargetArch) const { 528 return llvm::getSubDirectoryPath(Type, VSLayout, VCToolChainPath, TargetArch, 529 ""); 530 } 531 532 // Find the most recent version of Universal CRT or Windows 10 SDK. 533 // vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include 534 // directory by name and uses the last one of the list. 535 // So we compare entry names lexicographically to find the greatest one. 536 // Gets the library path required to link against the Windows SDK. 537 bool MSVCToolChain::getWindowsSDKLibraryPath(const ArgList &Args, 538 std::string &path) const { 539 std::string sdkPath; 540 int sdkMajor = 0; 541 std::string windowsSDKIncludeVersion; 542 std::string windowsSDKLibVersion; 543 544 path.clear(); 545 if (!llvm::getWindowsSDKDir(getVFS(), WinSdkDir, WinSdkVersion, WinSysRoot, 546 sdkPath, sdkMajor, windowsSDKIncludeVersion, 547 windowsSDKLibVersion)) 548 return false; 549 550 llvm::SmallString<128> libPath(sdkPath); 551 llvm::sys::path::append(libPath, "Lib"); 552 if (sdkMajor >= 10) 553 if (!(WinSdkDir.has_value() || WinSysRoot.has_value()) && 554 WinSdkVersion.has_value()) 555 windowsSDKLibVersion = *WinSdkVersion; 556 if (sdkMajor >= 8) 557 llvm::sys::path::append(libPath, windowsSDKLibVersion, "um"); 558 return llvm::appendArchToWindowsSDKLibPath(sdkMajor, libPath, getArch(), 559 path); 560 } 561 562 bool MSVCToolChain::useUniversalCRT() const { 563 return llvm::useUniversalCRT(VSLayout, VCToolChainPath, getArch(), getVFS()); 564 } 565 566 bool MSVCToolChain::getUniversalCRTLibraryPath(const ArgList &Args, 567 std::string &Path) const { 568 std::string UniversalCRTSdkPath; 569 std::string UCRTVersion; 570 571 Path.clear(); 572 if (!llvm::getUniversalCRTSdkDir(getVFS(), WinSdkDir, WinSdkVersion, 573 WinSysRoot, UniversalCRTSdkPath, 574 UCRTVersion)) 575 return false; 576 577 if (!(WinSdkDir.has_value() || WinSysRoot.has_value()) && 578 WinSdkVersion.has_value()) 579 UCRTVersion = *WinSdkVersion; 580 581 StringRef ArchName = llvm::archToWindowsSDKArch(getArch()); 582 if (ArchName.empty()) 583 return false; 584 585 llvm::SmallString<128> LibPath(UniversalCRTSdkPath); 586 llvm::sys::path::append(LibPath, "Lib", UCRTVersion, "ucrt", ArchName); 587 588 Path = std::string(LibPath); 589 return true; 590 } 591 592 static VersionTuple getMSVCVersionFromExe(const std::string &BinDir) { 593 VersionTuple Version; 594 #ifdef _WIN32 595 SmallString<128> ClExe(BinDir); 596 llvm::sys::path::append(ClExe, "cl.exe"); 597 598 std::wstring ClExeWide; 599 if (!llvm::ConvertUTF8toWide(ClExe.c_str(), ClExeWide)) 600 return Version; 601 602 const DWORD VersionSize = ::GetFileVersionInfoSizeW(ClExeWide.c_str(), 603 nullptr); 604 if (VersionSize == 0) 605 return Version; 606 607 SmallVector<uint8_t, 4 * 1024> VersionBlock(VersionSize); 608 if (!::GetFileVersionInfoW(ClExeWide.c_str(), 0, VersionSize, 609 VersionBlock.data())) 610 return Version; 611 612 VS_FIXEDFILEINFO *FileInfo = nullptr; 613 UINT FileInfoSize = 0; 614 if (!::VerQueryValueW(VersionBlock.data(), L"\\", 615 reinterpret_cast<LPVOID *>(&FileInfo), &FileInfoSize) || 616 FileInfoSize < sizeof(*FileInfo)) 617 return Version; 618 619 const unsigned Major = (FileInfo->dwFileVersionMS >> 16) & 0xFFFF; 620 const unsigned Minor = (FileInfo->dwFileVersionMS ) & 0xFFFF; 621 const unsigned Micro = (FileInfo->dwFileVersionLS >> 16) & 0xFFFF; 622 623 Version = VersionTuple(Major, Minor, Micro); 624 #endif 625 return Version; 626 } 627 628 void MSVCToolChain::AddSystemIncludeWithSubfolder( 629 const ArgList &DriverArgs, ArgStringList &CC1Args, 630 const std::string &folder, const Twine &subfolder1, const Twine &subfolder2, 631 const Twine &subfolder3) const { 632 llvm::SmallString<128> path(folder); 633 llvm::sys::path::append(path, subfolder1, subfolder2, subfolder3); 634 addSystemInclude(DriverArgs, CC1Args, path); 635 } 636 637 void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 638 ArgStringList &CC1Args) const { 639 if (DriverArgs.hasArg(options::OPT_nostdinc)) 640 return; 641 642 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 643 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, getDriver().ResourceDir, 644 "include"); 645 } 646 647 // Add %INCLUDE%-like directories from the -imsvc flag. 648 for (const auto &Path : DriverArgs.getAllArgValues(options::OPT__SLASH_imsvc)) 649 addSystemInclude(DriverArgs, CC1Args, Path); 650 651 auto AddSystemIncludesFromEnv = [&](StringRef Var) -> bool { 652 if (auto Val = llvm::sys::Process::GetEnv(Var)) { 653 SmallVector<StringRef, 8> Dirs; 654 StringRef(*Val).split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false); 655 if (!Dirs.empty()) { 656 addSystemIncludes(DriverArgs, CC1Args, Dirs); 657 return true; 658 } 659 } 660 return false; 661 }; 662 663 // Add %INCLUDE%-like dirs via /external:env: flags. 664 for (const auto &Var : 665 DriverArgs.getAllArgValues(options::OPT__SLASH_external_env)) { 666 AddSystemIncludesFromEnv(Var); 667 } 668 669 // Add DIA SDK include if requested. 670 if (const Arg *A = DriverArgs.getLastArg(options::OPT__SLASH_diasdkdir, 671 options::OPT__SLASH_winsysroot)) { 672 // cl.exe doesn't find the DIA SDK automatically, so this too requires 673 // explicit flags and doesn't automatically look in "DIA SDK" relative 674 // to the path we found for VCToolChainPath. 675 llvm::SmallString<128> DIASDKPath(A->getValue()); 676 if (A->getOption().getID() == options::OPT__SLASH_winsysroot) 677 llvm::sys::path::append(DIASDKPath, "DIA SDK"); 678 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, std::string(DIASDKPath), 679 "include"); 680 } 681 682 if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 683 return; 684 685 // Honor %INCLUDE% and %EXTERNAL_INCLUDE%. It should have essential search 686 // paths set by vcvarsall.bat. Skip if the user expressly set a vctoolsdir. 687 if (!DriverArgs.getLastArg(options::OPT__SLASH_vctoolsdir, 688 options::OPT__SLASH_winsysroot)) { 689 bool Found = AddSystemIncludesFromEnv("INCLUDE"); 690 Found |= AddSystemIncludesFromEnv("EXTERNAL_INCLUDE"); 691 if (Found) 692 return; 693 } 694 695 // When built with access to the proper Windows APIs, try to actually find 696 // the correct include paths first. 697 if (!VCToolChainPath.empty()) { 698 addSystemInclude(DriverArgs, CC1Args, 699 getSubDirectoryPath(llvm::SubDirectoryType::Include)); 700 addSystemInclude( 701 DriverArgs, CC1Args, 702 getSubDirectoryPath(llvm::SubDirectoryType::Include, "atlmfc")); 703 704 if (useUniversalCRT()) { 705 std::string UniversalCRTSdkPath; 706 std::string UCRTVersion; 707 if (llvm::getUniversalCRTSdkDir(getVFS(), WinSdkDir, WinSdkVersion, 708 WinSysRoot, UniversalCRTSdkPath, 709 UCRTVersion)) { 710 if (!(WinSdkDir.has_value() || WinSysRoot.has_value()) && 711 WinSdkVersion.has_value()) 712 UCRTVersion = *WinSdkVersion; 713 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath, 714 "Include", UCRTVersion, "ucrt"); 715 } 716 } 717 718 std::string WindowsSDKDir; 719 int major = 0; 720 std::string windowsSDKIncludeVersion; 721 std::string windowsSDKLibVersion; 722 if (llvm::getWindowsSDKDir(getVFS(), WinSdkDir, WinSdkVersion, WinSysRoot, 723 WindowsSDKDir, major, windowsSDKIncludeVersion, 724 windowsSDKLibVersion)) { 725 if (major >= 10) 726 if (!(WinSdkDir.has_value() || WinSysRoot.has_value()) && 727 WinSdkVersion.has_value()) 728 windowsSDKIncludeVersion = windowsSDKLibVersion = *WinSdkVersion; 729 if (major >= 8) { 730 // Note: windowsSDKIncludeVersion is empty for SDKs prior to v10. 731 // Anyway, llvm::sys::path::append is able to manage it. 732 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 733 "Include", windowsSDKIncludeVersion, 734 "shared"); 735 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 736 "Include", windowsSDKIncludeVersion, 737 "um"); 738 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 739 "Include", windowsSDKIncludeVersion, 740 "winrt"); 741 if (major >= 10) { 742 llvm::VersionTuple Tuple; 743 if (!Tuple.tryParse(windowsSDKIncludeVersion) && 744 Tuple.getSubminor().value_or(0) >= 17134) { 745 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 746 "Include", windowsSDKIncludeVersion, 747 "cppwinrt"); 748 } 749 } 750 } else { 751 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 752 "Include"); 753 } 754 } 755 756 return; 757 } 758 759 #if defined(_WIN32) 760 // As a fallback, select default install paths. 761 // FIXME: Don't guess drives and paths like this on Windows. 762 const StringRef Paths[] = { 763 "C:/Program Files/Microsoft Visual Studio 10.0/VC/include", 764 "C:/Program Files/Microsoft Visual Studio 9.0/VC/include", 765 "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include", 766 "C:/Program Files/Microsoft Visual Studio 8/VC/include", 767 "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include" 768 }; 769 addSystemIncludes(DriverArgs, CC1Args, Paths); 770 #endif 771 } 772 773 void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, 774 ArgStringList &CC1Args) const { 775 // FIXME: There should probably be logic here to find libc++ on Windows. 776 } 777 778 VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D, 779 const ArgList &Args) const { 780 bool IsWindowsMSVC = getTriple().isWindowsMSVCEnvironment(); 781 VersionTuple MSVT = ToolChain::computeMSVCVersion(D, Args); 782 if (MSVT.empty()) 783 MSVT = getTriple().getEnvironmentVersion(); 784 if (MSVT.empty() && IsWindowsMSVC) 785 MSVT = 786 getMSVCVersionFromExe(getSubDirectoryPath(llvm::SubDirectoryType::Bin)); 787 if (MSVT.empty() && 788 Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, 789 IsWindowsMSVC)) { 790 // -fms-compatibility-version=19.33 is default, aka 2022, 17.3 791 // NOTE: when changing this value, also update 792 // clang/docs/CommandGuide/clang.rst and clang/docs/UsersManual.rst 793 // accordingly. 794 MSVT = VersionTuple(19, 33); 795 } 796 return MSVT; 797 } 798 799 std::string 800 MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args, 801 types::ID InputType) const { 802 // The MSVC version doesn't care about the architecture, even though it 803 // may look at the triple internally. 804 VersionTuple MSVT = computeMSVCVersion(/*D=*/nullptr, Args); 805 MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().value_or(0), 806 MSVT.getSubminor().value_or(0)); 807 808 // For the rest of the triple, however, a computed architecture name may 809 // be needed. 810 llvm::Triple Triple(ToolChain::ComputeEffectiveClangTriple(Args, InputType)); 811 if (Triple.getEnvironment() == llvm::Triple::MSVC) { 812 StringRef ObjFmt = Triple.getEnvironmentName().split('-').second; 813 if (ObjFmt.empty()) 814 Triple.setEnvironmentName((Twine("msvc") + MSVT.getAsString()).str()); 815 else 816 Triple.setEnvironmentName( 817 (Twine("msvc") + MSVT.getAsString() + Twine('-') + ObjFmt).str()); 818 } 819 return Triple.getTriple(); 820 } 821 822 SanitizerMask MSVCToolChain::getSupportedSanitizers() const { 823 SanitizerMask Res = ToolChain::getSupportedSanitizers(); 824 Res |= SanitizerKind::Address; 825 Res |= SanitizerKind::PointerCompare; 826 Res |= SanitizerKind::PointerSubtract; 827 Res |= SanitizerKind::Fuzzer; 828 Res |= SanitizerKind::FuzzerNoLink; 829 Res &= ~SanitizerKind::CFIMFCall; 830 return Res; 831 } 832 833 static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL, 834 bool SupportsForcingFramePointer, 835 const char *ExpandChar, const OptTable &Opts) { 836 assert(A->getOption().matches(options::OPT__SLASH_O)); 837 838 StringRef OptStr = A->getValue(); 839 for (size_t I = 0, E = OptStr.size(); I != E; ++I) { 840 const char &OptChar = *(OptStr.data() + I); 841 switch (OptChar) { 842 default: 843 break; 844 case '1': 845 case '2': 846 case 'x': 847 case 'd': 848 // Ignore /O[12xd] flags that aren't the last one on the command line. 849 // Only the last one gets expanded. 850 if (&OptChar != ExpandChar) { 851 A->claim(); 852 break; 853 } 854 if (OptChar == 'd') { 855 DAL.AddFlagArg(A, Opts.getOption(options::OPT_O0)); 856 } else { 857 if (OptChar == '1') { 858 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s"); 859 } else if (OptChar == '2' || OptChar == 'x') { 860 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin)); 861 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2"); 862 } 863 if (SupportsForcingFramePointer && 864 !DAL.hasArgNoClaim(options::OPT_fno_omit_frame_pointer)) 865 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fomit_frame_pointer)); 866 if (OptChar == '1' || OptChar == '2') 867 DAL.AddFlagArg(A, Opts.getOption(options::OPT_ffunction_sections)); 868 } 869 break; 870 case 'b': 871 if (I + 1 != E && isdigit(OptStr[I + 1])) { 872 switch (OptStr[I + 1]) { 873 case '0': 874 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_inline)); 875 break; 876 case '1': 877 DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_hint_functions)); 878 break; 879 case '2': 880 DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_functions)); 881 break; 882 } 883 ++I; 884 } 885 break; 886 case 'g': 887 A->claim(); 888 break; 889 case 'i': 890 if (I + 1 != E && OptStr[I + 1] == '-') { 891 ++I; 892 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin)); 893 } else { 894 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin)); 895 } 896 break; 897 case 's': 898 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s"); 899 break; 900 case 't': 901 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2"); 902 break; 903 case 'y': { 904 bool OmitFramePointer = true; 905 if (I + 1 != E && OptStr[I + 1] == '-') { 906 OmitFramePointer = false; 907 ++I; 908 } 909 if (SupportsForcingFramePointer) { 910 if (OmitFramePointer) 911 DAL.AddFlagArg(A, 912 Opts.getOption(options::OPT_fomit_frame_pointer)); 913 else 914 DAL.AddFlagArg( 915 A, Opts.getOption(options::OPT_fno_omit_frame_pointer)); 916 } else { 917 // Don't warn about /Oy- in x86-64 builds (where 918 // SupportsForcingFramePointer is false). The flag having no effect 919 // there is a compiler-internal optimization, and people shouldn't have 920 // to special-case their build files for x86-64 clang-cl. 921 A->claim(); 922 } 923 break; 924 } 925 } 926 } 927 } 928 929 static void TranslateDArg(Arg *A, llvm::opt::DerivedArgList &DAL, 930 const OptTable &Opts) { 931 assert(A->getOption().matches(options::OPT_D)); 932 933 StringRef Val = A->getValue(); 934 size_t Hash = Val.find('#'); 935 if (Hash == StringRef::npos || Hash > Val.find('=')) { 936 DAL.append(A); 937 return; 938 } 939 940 std::string NewVal = std::string(Val); 941 NewVal[Hash] = '='; 942 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_D), NewVal); 943 } 944 945 static void TranslatePermissive(Arg *A, llvm::opt::DerivedArgList &DAL, 946 const OptTable &Opts) { 947 DAL.AddFlagArg(A, Opts.getOption(options::OPT__SLASH_Zc_twoPhase_)); 948 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_operator_names)); 949 } 950 951 static void TranslatePermissiveMinus(Arg *A, llvm::opt::DerivedArgList &DAL, 952 const OptTable &Opts) { 953 DAL.AddFlagArg(A, Opts.getOption(options::OPT__SLASH_Zc_twoPhase)); 954 DAL.AddFlagArg(A, Opts.getOption(options::OPT_foperator_names)); 955 } 956 957 llvm::opt::DerivedArgList * 958 MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args, 959 StringRef BoundArch, 960 Action::OffloadKind OFK) const { 961 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); 962 const OptTable &Opts = getDriver().getOpts(); 963 964 // /Oy and /Oy- don't have an effect on X86-64 965 bool SupportsForcingFramePointer = getArch() != llvm::Triple::x86_64; 966 967 // The -O[12xd] flag actually expands to several flags. We must desugar the 968 // flags so that options embedded can be negated. For example, the '-O2' flag 969 // enables '-Oy'. Expanding '-O2' into its constituent flags allows us to 970 // correctly handle '-O2 -Oy-' where the trailing '-Oy-' disables a single 971 // aspect of '-O2'. 972 // 973 // Note that this expansion logic only applies to the *last* of '[12xd]'. 974 975 // First step is to search for the character we'd like to expand. 976 const char *ExpandChar = nullptr; 977 for (Arg *A : Args.filtered(options::OPT__SLASH_O)) { 978 StringRef OptStr = A->getValue(); 979 for (size_t I = 0, E = OptStr.size(); I != E; ++I) { 980 char OptChar = OptStr[I]; 981 char PrevChar = I > 0 ? OptStr[I - 1] : '0'; 982 if (PrevChar == 'b') { 983 // OptChar does not expand; it's an argument to the previous char. 984 continue; 985 } 986 if (OptChar == '1' || OptChar == '2' || OptChar == 'x' || OptChar == 'd') 987 ExpandChar = OptStr.data() + I; 988 } 989 } 990 991 for (Arg *A : Args) { 992 if (A->getOption().matches(options::OPT__SLASH_O)) { 993 // The -O flag actually takes an amalgam of other options. For example, 994 // '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'. 995 TranslateOptArg(A, *DAL, SupportsForcingFramePointer, ExpandChar, Opts); 996 } else if (A->getOption().matches(options::OPT_D)) { 997 // Translate -Dfoo#bar into -Dfoo=bar. 998 TranslateDArg(A, *DAL, Opts); 999 } else if (A->getOption().matches(options::OPT__SLASH_permissive)) { 1000 // Expand /permissive 1001 TranslatePermissive(A, *DAL, Opts); 1002 } else if (A->getOption().matches(options::OPT__SLASH_permissive_)) { 1003 // Expand /permissive- 1004 TranslatePermissiveMinus(A, *DAL, Opts); 1005 } else if (OFK != Action::OFK_HIP) { 1006 // HIP Toolchain translates input args by itself. 1007 DAL->append(A); 1008 } 1009 } 1010 1011 return DAL; 1012 } 1013 1014 void MSVCToolChain::addClangTargetOptions( 1015 const ArgList &DriverArgs, ArgStringList &CC1Args, 1016 Action::OffloadKind DeviceOffloadKind) const { 1017 // MSVC STL kindly allows removing all usages of typeid by defining 1018 // _HAS_STATIC_RTTI to 0. Do so, when compiling with -fno-rtti 1019 if (DriverArgs.hasFlag(options::OPT_fno_rtti, options::OPT_frtti, 1020 /*Default=*/false)) 1021 CC1Args.push_back("-D_HAS_STATIC_RTTI=0"); 1022 } 1023