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/ADT/StringSwitch.h" 22#include "llvm/Option/Arg.h" 23#include "llvm/Option/ArgList.h" 24#include "llvm/Support/ConvertUTF.h" 25#include "llvm/Support/ErrorHandling.h" 26#include "llvm/Support/FileSystem.h" 27#include "llvm/Support/Host.h" 28#include "llvm/Support/MemoryBuffer.h" 29#include "llvm/Support/Path.h" 30#include "llvm/Support/Process.h" 31#include "llvm/Support/VirtualFileSystem.h" 32#include <cstdio> 33 34#ifdef _WIN32 35 #define WIN32_LEAN_AND_MEAN 36 #define NOGDI 37 #ifndef NOMINMAX 38 #define NOMINMAX 39 #endif 40 #include <windows.h> 41#endif 42 43#ifdef _MSC_VER 44// Don't support SetupApi on MinGW. 45#define USE_MSVC_SETUP_API 46 47// Make sure this comes before MSVCSetupApi.h 48#include <comdef.h> 49 50#include "MSVCSetupApi.h" 51#include "llvm/Support/COM.h" 52_COM_SMARTPTR_TYPEDEF(ISetupConfiguration, __uuidof(ISetupConfiguration)); 53_COM_SMARTPTR_TYPEDEF(ISetupConfiguration2, __uuidof(ISetupConfiguration2)); 54_COM_SMARTPTR_TYPEDEF(ISetupHelper, __uuidof(ISetupHelper)); 55_COM_SMARTPTR_TYPEDEF(IEnumSetupInstances, __uuidof(IEnumSetupInstances)); 56_COM_SMARTPTR_TYPEDEF(ISetupInstance, __uuidof(ISetupInstance)); 57_COM_SMARTPTR_TYPEDEF(ISetupInstance2, __uuidof(ISetupInstance2)); 58#endif 59 60using namespace clang::driver; 61using namespace clang::driver::toolchains; 62using namespace clang::driver::tools; 63using namespace clang; 64using namespace llvm::opt; 65 66static bool canExecute(llvm::vfs::FileSystem &VFS, StringRef Path) { 67 auto Status = VFS.status(Path); 68 if (!Status) 69 return false; 70 return (Status->getPermissions() & llvm::sys::fs::perms::all_exe) != 0; 71} 72 73// Defined below. 74// Forward declare this so there aren't too many things above the constructor. 75static bool getSystemRegistryString(const char *keyPath, const char *valueName, 76 std::string &value, std::string *phValue); 77 78static std::string getHighestNumericTupleInDirectory(llvm::vfs::FileSystem &VFS, 79 StringRef Directory) { 80 std::string Highest; 81 llvm::VersionTuple HighestTuple; 82 83 std::error_code EC; 84 for (llvm::vfs::directory_iterator DirIt = VFS.dir_begin(Directory, EC), 85 DirEnd; 86 !EC && DirIt != DirEnd; DirIt.increment(EC)) { 87 auto Status = VFS.status(DirIt->path()); 88 if (!Status || !Status->isDirectory()) 89 continue; 90 StringRef CandidateName = llvm::sys::path::filename(DirIt->path()); 91 llvm::VersionTuple Tuple; 92 if (Tuple.tryParse(CandidateName)) // tryParse() returns true on error. 93 continue; 94 if (Tuple > HighestTuple) { 95 HighestTuple = Tuple; 96 Highest = CandidateName.str(); 97 } 98 } 99 100 return Highest; 101} 102 103// Check command line arguments to try and find a toolchain. 104static bool 105findVCToolChainViaCommandLine(llvm::vfs::FileSystem &VFS, const ArgList &Args, 106 std::string &Path, 107 MSVCToolChain::ToolsetLayout &VSLayout) { 108 // Don't validate the input; trust the value supplied by the user. 109 // The primary motivation is to prevent unnecessary file and registry access. 110 if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir, 111 options::OPT__SLASH_winsysroot)) { 112 if (A->getOption().getID() == options::OPT__SLASH_winsysroot) { 113 llvm::SmallString<128> ToolsPath(A->getValue()); 114 llvm::sys::path::append(ToolsPath, "VC", "Tools", "MSVC"); 115 std::string VCToolsVersion; 116 if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsversion)) 117 VCToolsVersion = A->getValue(); 118 else 119 VCToolsVersion = getHighestNumericTupleInDirectory(VFS, ToolsPath); 120 llvm::sys::path::append(ToolsPath, VCToolsVersion); 121 Path = std::string(ToolsPath.str()); 122 } else { 123 Path = A->getValue(); 124 } 125 VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer; 126 return true; 127 } 128 return false; 129} 130 131// Check various environment variables to try and find a toolchain. 132static bool 133findVCToolChainViaEnvironment(llvm::vfs::FileSystem &VFS, std::string &Path, 134 MSVCToolChain::ToolsetLayout &VSLayout) { 135 // These variables are typically set by vcvarsall.bat 136 // when launching a developer command prompt. 137 if (llvm::Optional<std::string> VCToolsInstallDir = 138 llvm::sys::Process::GetEnv("VCToolsInstallDir")) { 139 // This is only set by newer Visual Studios, and it leads straight to 140 // the toolchain directory. 141 Path = std::move(*VCToolsInstallDir); 142 VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer; 143 return true; 144 } 145 if (llvm::Optional<std::string> VCInstallDir = 146 llvm::sys::Process::GetEnv("VCINSTALLDIR")) { 147 // If the previous variable isn't set but this one is, then we've found 148 // an older Visual Studio. This variable is set by newer Visual Studios too, 149 // so this check has to appear second. 150 // In older Visual Studios, the VC directory is the toolchain. 151 Path = std::move(*VCInstallDir); 152 VSLayout = MSVCToolChain::ToolsetLayout::OlderVS; 153 return true; 154 } 155 156 // We couldn't find any VC environment variables. Let's walk through PATH and 157 // see if it leads us to a VC toolchain bin directory. If it does, pick the 158 // first one that we find. 159 if (llvm::Optional<std::string> PathEnv = 160 llvm::sys::Process::GetEnv("PATH")) { 161 llvm::SmallVector<llvm::StringRef, 8> PathEntries; 162 llvm::StringRef(*PathEnv).split(PathEntries, llvm::sys::EnvPathSeparator); 163 for (llvm::StringRef PathEntry : PathEntries) { 164 if (PathEntry.empty()) 165 continue; 166 167 llvm::SmallString<256> ExeTestPath; 168 169 // If cl.exe doesn't exist, then this definitely isn't a VC toolchain. 170 ExeTestPath = PathEntry; 171 llvm::sys::path::append(ExeTestPath, "cl.exe"); 172 if (!VFS.exists(ExeTestPath)) 173 continue; 174 175 // cl.exe existing isn't a conclusive test for a VC toolchain; clang also 176 // has a cl.exe. So let's check for link.exe too. 177 ExeTestPath = PathEntry; 178 llvm::sys::path::append(ExeTestPath, "link.exe"); 179 if (!VFS.exists(ExeTestPath)) 180 continue; 181 182 // whatever/VC/bin --> old toolchain, VC dir is toolchain dir. 183 llvm::StringRef TestPath = PathEntry; 184 bool IsBin = llvm::sys::path::filename(TestPath).equals_lower("bin"); 185 if (!IsBin) { 186 // Strip any architecture subdir like "amd64". 187 TestPath = llvm::sys::path::parent_path(TestPath); 188 IsBin = llvm::sys::path::filename(TestPath).equals_lower("bin"); 189 } 190 if (IsBin) { 191 llvm::StringRef ParentPath = llvm::sys::path::parent_path(TestPath); 192 llvm::StringRef ParentFilename = llvm::sys::path::filename(ParentPath); 193 if (ParentFilename.equals_lower("VC")) { 194 Path = std::string(ParentPath); 195 VSLayout = MSVCToolChain::ToolsetLayout::OlderVS; 196 return true; 197 } 198 if (ParentFilename.equals_lower("x86ret") || 199 ParentFilename.equals_lower("x86chk") || 200 ParentFilename.equals_lower("amd64ret") || 201 ParentFilename.equals_lower("amd64chk")) { 202 Path = std::string(ParentPath); 203 VSLayout = MSVCToolChain::ToolsetLayout::DevDivInternal; 204 return true; 205 } 206 207 } else { 208 // This could be a new (>=VS2017) toolchain. If it is, we should find 209 // path components with these prefixes when walking backwards through 210 // the path. 211 // Note: empty strings match anything. 212 llvm::StringRef ExpectedPrefixes[] = {"", "Host", "bin", "", 213 "MSVC", "Tools", "VC"}; 214 215 auto It = llvm::sys::path::rbegin(PathEntry); 216 auto End = llvm::sys::path::rend(PathEntry); 217 for (llvm::StringRef Prefix : ExpectedPrefixes) { 218 if (It == End) 219 goto NotAToolChain; 220 if (!It->startswith_lower(Prefix)) 221 goto NotAToolChain; 222 ++It; 223 } 224 225 // We've found a new toolchain! 226 // Back up 3 times (/bin/Host/arch) to get the root path. 227 llvm::StringRef ToolChainPath(PathEntry); 228 for (int i = 0; i < 3; ++i) 229 ToolChainPath = llvm::sys::path::parent_path(ToolChainPath); 230 231 Path = std::string(ToolChainPath); 232 VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer; 233 return true; 234 } 235 236 NotAToolChain: 237 continue; 238 } 239 } 240 return false; 241} 242 243// Query the Setup Config server for installs, then pick the newest version 244// and find its default VC toolchain. 245// This is the preferred way to discover new Visual Studios, as they're no 246// longer listed in the registry. 247static bool 248findVCToolChainViaSetupConfig(llvm::vfs::FileSystem &VFS, std::string &Path, 249 MSVCToolChain::ToolsetLayout &VSLayout) { 250#if !defined(USE_MSVC_SETUP_API) 251 return false; 252#else 253 // FIXME: This really should be done once in the top-level program's main 254 // function, as it may have already been initialized with a different 255 // threading model otherwise. 256 llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::SingleThreaded); 257 HRESULT HR; 258 259 // _com_ptr_t will throw a _com_error if a COM calls fail. 260 // The LLVM coding standards forbid exception handling, so we'll have to 261 // stop them from being thrown in the first place. 262 // The destructor will put the regular error handler back when we leave 263 // this scope. 264 struct SuppressCOMErrorsRAII { 265 static void __stdcall handler(HRESULT hr, IErrorInfo *perrinfo) {} 266 267 SuppressCOMErrorsRAII() { _set_com_error_handler(handler); } 268 269 ~SuppressCOMErrorsRAII() { _set_com_error_handler(_com_raise_error); } 270 271 } COMErrorSuppressor; 272 273 ISetupConfigurationPtr Query; 274 HR = Query.CreateInstance(__uuidof(SetupConfiguration)); 275 if (FAILED(HR)) 276 return false; 277 278 IEnumSetupInstancesPtr EnumInstances; 279 HR = ISetupConfiguration2Ptr(Query)->EnumAllInstances(&EnumInstances); 280 if (FAILED(HR)) 281 return false; 282 283 ISetupInstancePtr Instance; 284 HR = EnumInstances->Next(1, &Instance, nullptr); 285 if (HR != S_OK) 286 return false; 287 288 ISetupInstancePtr NewestInstance; 289 Optional<uint64_t> NewestVersionNum; 290 do { 291 bstr_t VersionString; 292 uint64_t VersionNum; 293 HR = Instance->GetInstallationVersion(VersionString.GetAddress()); 294 if (FAILED(HR)) 295 continue; 296 HR = ISetupHelperPtr(Query)->ParseVersion(VersionString, &VersionNum); 297 if (FAILED(HR)) 298 continue; 299 if (!NewestVersionNum || (VersionNum > NewestVersionNum)) { 300 NewestInstance = Instance; 301 NewestVersionNum = VersionNum; 302 } 303 } while ((HR = EnumInstances->Next(1, &Instance, nullptr)) == S_OK); 304 305 if (!NewestInstance) 306 return false; 307 308 bstr_t VCPathWide; 309 HR = NewestInstance->ResolvePath(L"VC", VCPathWide.GetAddress()); 310 if (FAILED(HR)) 311 return false; 312 313 std::string VCRootPath; 314 llvm::convertWideToUTF8(std::wstring(VCPathWide), VCRootPath); 315 316 llvm::SmallString<256> ToolsVersionFilePath(VCRootPath); 317 llvm::sys::path::append(ToolsVersionFilePath, "Auxiliary", "Build", 318 "Microsoft.VCToolsVersion.default.txt"); 319 320 auto ToolsVersionFile = llvm::MemoryBuffer::getFile(ToolsVersionFilePath); 321 if (!ToolsVersionFile) 322 return false; 323 324 llvm::SmallString<256> ToolchainPath(VCRootPath); 325 llvm::sys::path::append(ToolchainPath, "Tools", "MSVC", 326 ToolsVersionFile->get()->getBuffer().rtrim()); 327 auto Status = VFS.status(ToolchainPath); 328 if (!Status || !Status->isDirectory()) 329 return false; 330 331 Path = std::string(ToolchainPath.str()); 332 VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer; 333 return true; 334#endif 335} 336 337// Look in the registry for Visual Studio installs, and use that to get 338// a toolchain path. VS2017 and newer don't get added to the registry. 339// So if we find something here, we know that it's an older version. 340static bool findVCToolChainViaRegistry(std::string &Path, 341 MSVCToolChain::ToolsetLayout &VSLayout) { 342 std::string VSInstallPath; 343 if (getSystemRegistryString(R"(SOFTWARE\Microsoft\VisualStudio\$VERSION)", 344 "InstallDir", VSInstallPath, nullptr) || 345 getSystemRegistryString(R"(SOFTWARE\Microsoft\VCExpress\$VERSION)", 346 "InstallDir", VSInstallPath, nullptr)) { 347 if (!VSInstallPath.empty()) { 348 llvm::SmallString<256> VCPath(llvm::StringRef( 349 VSInstallPath.c_str(), VSInstallPath.find(R"(\Common7\IDE)"))); 350 llvm::sys::path::append(VCPath, "VC"); 351 352 Path = std::string(VCPath.str()); 353 VSLayout = MSVCToolChain::ToolsetLayout::OlderVS; 354 return true; 355 } 356 } 357 return false; 358} 359 360// Try to find Exe from a Visual Studio distribution. This first tries to find 361// an installed copy of Visual Studio and, failing that, looks in the PATH, 362// making sure that whatever executable that's found is not a same-named exe 363// from clang itself to prevent clang from falling back to itself. 364static std::string FindVisualStudioExecutable(const ToolChain &TC, 365 const char *Exe) { 366 const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC); 367 SmallString<128> FilePath(MSVC.getSubDirectoryPath( 368 toolchains::MSVCToolChain::SubDirectoryType::Bin)); 369 llvm::sys::path::append(FilePath, Exe); 370 return std::string(canExecute(TC.getVFS(), FilePath) ? FilePath.str() : Exe); 371} 372 373void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, 374 const InputInfo &Output, 375 const InputInfoList &Inputs, 376 const ArgList &Args, 377 const char *LinkingOutput) const { 378 ArgStringList CmdArgs; 379 380 auto &TC = static_cast<const toolchains::MSVCToolChain &>(getToolChain()); 381 382 assert((Output.isFilename() || Output.isNothing()) && "invalid output"); 383 if (Output.isFilename()) 384 CmdArgs.push_back( 385 Args.MakeArgString(std::string("-out:") + Output.getFilename())); 386 387 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) && 388 !C.getDriver().IsCLMode()) { 389 CmdArgs.push_back("-defaultlib:libcmt"); 390 CmdArgs.push_back("-defaultlib:oldnames"); 391 } 392 393 // If the VC environment hasn't been configured (perhaps because the user 394 // did not run vcvarsall), try to build a consistent link environment. If 395 // the environment variable is set however, assume the user knows what 396 // they're doing. If the user passes /vctoolsdir or /winsdkdir, trust that 397 // over env vars. 398 if (!llvm::sys::Process::GetEnv("LIB") || 399 Args.getLastArg(options::OPT__SLASH_vctoolsdir, 400 options::OPT__SLASH_winsysroot)) { 401 CmdArgs.push_back(Args.MakeArgString( 402 Twine("-libpath:") + 403 TC.getSubDirectoryPath( 404 toolchains::MSVCToolChain::SubDirectoryType::Lib))); 405 CmdArgs.push_back(Args.MakeArgString( 406 Twine("-libpath:") + 407 TC.getSubDirectoryPath(toolchains::MSVCToolChain::SubDirectoryType::Lib, 408 "atlmfc"))); 409 } 410 if (!llvm::sys::Process::GetEnv("LIB") || 411 Args.getLastArg(options::OPT__SLASH_winsdkdir, 412 options::OPT__SLASH_winsysroot)) { 413 if (TC.useUniversalCRT()) { 414 std::string UniversalCRTLibPath; 415 if (TC.getUniversalCRTLibraryPath(Args, UniversalCRTLibPath)) 416 CmdArgs.push_back( 417 Args.MakeArgString(Twine("-libpath:") + UniversalCRTLibPath)); 418 } 419 std::string WindowsSdkLibPath; 420 if (TC.getWindowsSDKLibraryPath(Args, WindowsSdkLibPath)) 421 CmdArgs.push_back( 422 Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath)); 423 } 424 425 // Add the compiler-rt library directories to libpath if they exist to help 426 // the linker find the various sanitizer, builtin, and profiling runtimes. 427 for (const auto &LibPath : TC.getLibraryPaths()) { 428 if (TC.getVFS().exists(LibPath)) 429 CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath)); 430 } 431 auto CRTPath = TC.getCompilerRTPath(); 432 if (TC.getVFS().exists(CRTPath)) 433 CmdArgs.push_back(Args.MakeArgString("-libpath:" + CRTPath)); 434 435 if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L)) 436 for (const auto &LibPath : Args.getAllArgValues(options::OPT_L)) 437 CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath)); 438 439 CmdArgs.push_back("-nologo"); 440 441 if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7)) 442 CmdArgs.push_back("-debug"); 443 444 // Pass on /Brepro if it was passed to the compiler. 445 // Note that /Brepro maps to -mno-incremental-linker-compatible. 446 bool DefaultIncrementalLinkerCompatible = 447 C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment(); 448 if (!Args.hasFlag(options::OPT_mincremental_linker_compatible, 449 options::OPT_mno_incremental_linker_compatible, 450 DefaultIncrementalLinkerCompatible)) 451 CmdArgs.push_back("-Brepro"); 452 453 bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd, 454 options::OPT_shared); 455 if (DLL) { 456 CmdArgs.push_back(Args.MakeArgString("-dll")); 457 458 SmallString<128> ImplibName(Output.getFilename()); 459 llvm::sys::path::replace_extension(ImplibName, "lib"); 460 CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName)); 461 } 462 463 if (TC.getSanitizerArgs().needsFuzzer()) { 464 if (!Args.hasArg(options::OPT_shared)) 465 CmdArgs.push_back( 466 Args.MakeArgString(std::string("-wholearchive:") + 467 TC.getCompilerRTArgString(Args, "fuzzer"))); 468 CmdArgs.push_back(Args.MakeArgString("-debug")); 469 // Prevent the linker from padding sections we use for instrumentation 470 // arrays. 471 CmdArgs.push_back(Args.MakeArgString("-incremental:no")); 472 } 473 474 if (TC.getSanitizerArgs().needsAsanRt()) { 475 CmdArgs.push_back(Args.MakeArgString("-debug")); 476 CmdArgs.push_back(Args.MakeArgString("-incremental:no")); 477 if (TC.getSanitizerArgs().needsSharedRt() || 478 Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) { 479 for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"}) 480 CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib)); 481 // Make sure the dynamic runtime thunk is not optimized out at link time 482 // to ensure proper SEH handling. 483 CmdArgs.push_back(Args.MakeArgString( 484 TC.getArch() == llvm::Triple::x86 485 ? "-include:___asan_seh_interceptor" 486 : "-include:__asan_seh_interceptor")); 487 // Make sure the linker consider all object files from the dynamic runtime 488 // thunk. 489 CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") + 490 TC.getCompilerRT(Args, "asan_dynamic_runtime_thunk"))); 491 } else if (DLL) { 492 CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk")); 493 } else { 494 for (const auto &Lib : {"asan", "asan_cxx"}) { 495 CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib)); 496 // Make sure the linker consider all object files from the static lib. 497 // This is necessary because instrumented dlls need access to all the 498 // interface exported by the static lib in the main executable. 499 CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") + 500 TC.getCompilerRT(Args, Lib))); 501 } 502 } 503 } 504 505 Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link); 506 507 // Control Flow Guard checks 508 if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) { 509 StringRef GuardArgs = A->getValue(); 510 if (GuardArgs.equals_lower("cf") || GuardArgs.equals_lower("cf,nochecks")) { 511 // MSVC doesn't yet support the "nochecks" modifier. 512 CmdArgs.push_back("-guard:cf"); 513 } else if (GuardArgs.equals_lower("cf-")) { 514 CmdArgs.push_back("-guard:cf-"); 515 } else if (GuardArgs.equals_lower("ehcont")) { 516 CmdArgs.push_back("-guard:ehcont"); 517 } else if (GuardArgs.equals_lower("ehcont-")) { 518 CmdArgs.push_back("-guard:ehcont-"); 519 } 520 } 521 522 if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, 523 options::OPT_fno_openmp, false)) { 524 CmdArgs.push_back("-nodefaultlib:vcomp.lib"); 525 CmdArgs.push_back("-nodefaultlib:vcompd.lib"); 526 CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") + 527 TC.getDriver().Dir + "/../lib")); 528 switch (TC.getDriver().getOpenMPRuntime(Args)) { 529 case Driver::OMPRT_OMP: 530 CmdArgs.push_back("-defaultlib:libomp.lib"); 531 break; 532 case Driver::OMPRT_IOMP5: 533 CmdArgs.push_back("-defaultlib:libiomp5md.lib"); 534 break; 535 case Driver::OMPRT_GOMP: 536 break; 537 case Driver::OMPRT_Unknown: 538 // Already diagnosed. 539 break; 540 } 541 } 542 543 // Add compiler-rt lib in case if it was explicitly 544 // specified as an argument for --rtlib option. 545 if (!Args.hasArg(options::OPT_nostdlib)) { 546 AddRunTimeLibs(TC, TC.getDriver(), CmdArgs, Args); 547 } 548 549 // Add filenames, libraries, and other linker inputs. 550 for (const auto &Input : Inputs) { 551 if (Input.isFilename()) { 552 CmdArgs.push_back(Input.getFilename()); 553 continue; 554 } 555 556 const Arg &A = Input.getInputArg(); 557 558 // Render -l options differently for the MSVC linker. 559 if (A.getOption().matches(options::OPT_l)) { 560 StringRef Lib = A.getValue(); 561 const char *LinkLibArg; 562 if (Lib.endswith(".lib")) 563 LinkLibArg = Args.MakeArgString(Lib); 564 else 565 LinkLibArg = Args.MakeArgString(Lib + ".lib"); 566 CmdArgs.push_back(LinkLibArg); 567 continue; 568 } 569 570 // Otherwise, this is some other kind of linker input option like -Wl, -z, 571 // or -L. Render it, even if MSVC doesn't understand it. 572 A.renderAsInput(Args, CmdArgs); 573 } 574 575 TC.addProfileRTLibs(Args, CmdArgs); 576 577 std::vector<const char *> Environment; 578 579 // We need to special case some linker paths. In the case of lld, we need to 580 // translate 'lld' into 'lld-link', and in the case of the regular msvc 581 // linker, we need to use a special search algorithm. 582 llvm::SmallString<128> linkPath; 583 StringRef Linker 584 = Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER); 585 if (Linker.empty()) 586 Linker = "link"; 587 if (Linker.equals_lower("lld")) 588 Linker = "lld-link"; 589 590 if (Linker.equals_lower("link")) { 591 // If we're using the MSVC linker, it's not sufficient to just use link 592 // from the program PATH, because other environments like GnuWin32 install 593 // their own link.exe which may come first. 594 linkPath = FindVisualStudioExecutable(TC, "link.exe"); 595 596 if (!TC.FoundMSVCInstall() && !canExecute(TC.getVFS(), linkPath)) { 597 llvm::SmallString<128> ClPath; 598 ClPath = TC.GetProgramPath("cl.exe"); 599 if (canExecute(TC.getVFS(), ClPath)) { 600 linkPath = llvm::sys::path::parent_path(ClPath); 601 llvm::sys::path::append(linkPath, "link.exe"); 602 if (!canExecute(TC.getVFS(), linkPath)) 603 C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found); 604 } else { 605 C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found); 606 } 607 } 608 609#ifdef _WIN32 610 // When cross-compiling with VS2017 or newer, link.exe expects to have 611 // its containing bin directory at the top of PATH, followed by the 612 // native target bin directory. 613 // e.g. when compiling for x86 on an x64 host, PATH should start with: 614 // /bin/Hostx64/x86;/bin/Hostx64/x64 615 // This doesn't attempt to handle ToolsetLayout::DevDivInternal. 616 if (TC.getIsVS2017OrNewer() && 617 llvm::Triple(llvm::sys::getProcessTriple()).getArch() != TC.getArch()) { 618 auto HostArch = llvm::Triple(llvm::sys::getProcessTriple()).getArch(); 619 620 auto EnvBlockWide = 621 std::unique_ptr<wchar_t[], decltype(&FreeEnvironmentStringsW)>( 622 GetEnvironmentStringsW(), FreeEnvironmentStringsW); 623 if (!EnvBlockWide) 624 goto SkipSettingEnvironment; 625 626 size_t EnvCount = 0; 627 size_t EnvBlockLen = 0; 628 while (EnvBlockWide[EnvBlockLen] != L'\0') { 629 ++EnvCount; 630 EnvBlockLen += std::wcslen(&EnvBlockWide[EnvBlockLen]) + 631 1 /*string null-terminator*/; 632 } 633 ++EnvBlockLen; // add the block null-terminator 634 635 std::string EnvBlock; 636 if (!llvm::convertUTF16ToUTF8String( 637 llvm::ArrayRef<char>(reinterpret_cast<char *>(EnvBlockWide.get()), 638 EnvBlockLen * sizeof(EnvBlockWide[0])), 639 EnvBlock)) 640 goto SkipSettingEnvironment; 641 642 Environment.reserve(EnvCount); 643 644 // Now loop over each string in the block and copy them into the 645 // environment vector, adjusting the PATH variable as needed when we 646 // find it. 647 for (const char *Cursor = EnvBlock.data(); *Cursor != '\0';) { 648 llvm::StringRef EnvVar(Cursor); 649 if (EnvVar.startswith_lower("path=")) { 650 using SubDirectoryType = toolchains::MSVCToolChain::SubDirectoryType; 651 constexpr size_t PrefixLen = 5; // strlen("path=") 652 Environment.push_back(Args.MakeArgString( 653 EnvVar.substr(0, PrefixLen) + 654 TC.getSubDirectoryPath(SubDirectoryType::Bin) + 655 llvm::Twine(llvm::sys::EnvPathSeparator) + 656 TC.getSubDirectoryPath(SubDirectoryType::Bin, "", HostArch) + 657 (EnvVar.size() > PrefixLen 658 ? llvm::Twine(llvm::sys::EnvPathSeparator) + 659 EnvVar.substr(PrefixLen) 660 : ""))); 661 } else { 662 Environment.push_back(Args.MakeArgString(EnvVar)); 663 } 664 Cursor += EnvVar.size() + 1 /*null-terminator*/; 665 } 666 } 667 SkipSettingEnvironment:; 668#endif 669 } else { 670 linkPath = TC.GetProgramPath(Linker.str().c_str()); 671 } 672 673 auto LinkCmd = std::make_unique<Command>( 674 JA, *this, ResponseFileSupport::AtFileUTF16(), 675 Args.MakeArgString(linkPath), CmdArgs, Inputs, Output); 676 if (!Environment.empty()) 677 LinkCmd->setEnvironment(Environment); 678 C.addCommand(std::move(LinkCmd)); 679} 680 681MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple, 682 const ArgList &Args) 683 : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args), 684 RocmInstallation(D, Triple, Args) { 685 getProgramPaths().push_back(getDriver().getInstalledDir()); 686 if (getDriver().getInstalledDir() != getDriver().Dir) 687 getProgramPaths().push_back(getDriver().Dir); 688 689 // Check the command line first, that's the user explicitly telling us what to 690 // use. Check the environment next, in case we're being invoked from a VS 691 // command prompt. Failing that, just try to find the newest Visual Studio 692 // version we can and use its default VC toolchain. 693 findVCToolChainViaCommandLine(getVFS(), Args, VCToolChainPath, VSLayout) || 694 findVCToolChainViaEnvironment(getVFS(), VCToolChainPath, VSLayout) || 695 findVCToolChainViaSetupConfig(getVFS(), VCToolChainPath, VSLayout) || 696 findVCToolChainViaRegistry(VCToolChainPath, VSLayout); 697} 698 699Tool *MSVCToolChain::buildLinker() const { 700 return new tools::visualstudio::Linker(*this); 701} 702 703Tool *MSVCToolChain::buildAssembler() const { 704 if (getTriple().isOSBinFormatMachO()) 705 return new tools::darwin::Assembler(*this); 706 getDriver().Diag(clang::diag::err_no_external_assembler); 707 return nullptr; 708} 709 710bool MSVCToolChain::IsIntegratedAssemblerDefault() const { 711 return true; 712} 713 714bool MSVCToolChain::IsUnwindTablesDefault(const ArgList &Args) const { 715 // Don't emit unwind tables by default for MachO targets. 716 if (getTriple().isOSBinFormatMachO()) 717 return false; 718 719 // All non-x86_32 Windows targets require unwind tables. However, LLVM 720 // doesn't know how to generate them for all targets, so only enable 721 // the ones that are actually implemented. 722 return getArch() == llvm::Triple::x86_64 || 723 getArch() == llvm::Triple::aarch64; 724} 725 726bool MSVCToolChain::isPICDefault() const { 727 return getArch() == llvm::Triple::x86_64; 728} 729 730bool MSVCToolChain::isPIEDefault() const { 731 return false; 732} 733 734bool MSVCToolChain::isPICDefaultForced() const { 735 return getArch() == llvm::Triple::x86_64; 736} 737 738void MSVCToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs, 739 ArgStringList &CC1Args) const { 740 CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args); 741} 742 743void MSVCToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs, 744 ArgStringList &CC1Args) const { 745 RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args); 746} 747 748void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const { 749 CudaInstallation.print(OS); 750 RocmInstallation.print(OS); 751} 752 753// Windows SDKs and VC Toolchains group their contents into subdirectories based 754// on the target architecture. This function converts an llvm::Triple::ArchType 755// to the corresponding subdirectory name. 756static const char *llvmArchToWindowsSDKArch(llvm::Triple::ArchType Arch) { 757 using ArchType = llvm::Triple::ArchType; 758 switch (Arch) { 759 case ArchType::x86: 760 return "x86"; 761 case ArchType::x86_64: 762 return "x64"; 763 case ArchType::arm: 764 return "arm"; 765 case ArchType::aarch64: 766 return "arm64"; 767 default: 768 return ""; 769 } 770} 771 772// Similar to the above function, but for Visual Studios before VS2017. 773static const char *llvmArchToLegacyVCArch(llvm::Triple::ArchType Arch) { 774 using ArchType = llvm::Triple::ArchType; 775 switch (Arch) { 776 case ArchType::x86: 777 // x86 is default in legacy VC toolchains. 778 // e.g. x86 libs are directly in /lib as opposed to /lib/x86. 779 return ""; 780 case ArchType::x86_64: 781 return "amd64"; 782 case ArchType::arm: 783 return "arm"; 784 case ArchType::aarch64: 785 return "arm64"; 786 default: 787 return ""; 788 } 789} 790 791// Similar to the above function, but for DevDiv internal builds. 792static const char *llvmArchToDevDivInternalArch(llvm::Triple::ArchType Arch) { 793 using ArchType = llvm::Triple::ArchType; 794 switch (Arch) { 795 case ArchType::x86: 796 return "i386"; 797 case ArchType::x86_64: 798 return "amd64"; 799 case ArchType::arm: 800 return "arm"; 801 case ArchType::aarch64: 802 return "arm64"; 803 default: 804 return ""; 805 } 806} 807 808// Get the path to a specific subdirectory in the current toolchain for 809// a given target architecture. 810// VS2017 changed the VC toolchain layout, so this should be used instead 811// of hardcoding paths. 812std::string 813MSVCToolChain::getSubDirectoryPath(SubDirectoryType Type, 814 llvm::StringRef SubdirParent, 815 llvm::Triple::ArchType TargetArch) const { 816 const char *SubdirName; 817 const char *IncludeName; 818 switch (VSLayout) { 819 case ToolsetLayout::OlderVS: 820 SubdirName = llvmArchToLegacyVCArch(TargetArch); 821 IncludeName = "include"; 822 break; 823 case ToolsetLayout::VS2017OrNewer: 824 SubdirName = llvmArchToWindowsSDKArch(TargetArch); 825 IncludeName = "include"; 826 break; 827 case ToolsetLayout::DevDivInternal: 828 SubdirName = llvmArchToDevDivInternalArch(TargetArch); 829 IncludeName = "inc"; 830 break; 831 } 832 833 llvm::SmallString<256> Path(VCToolChainPath); 834 if (!SubdirParent.empty()) 835 llvm::sys::path::append(Path, SubdirParent); 836 837 switch (Type) { 838 case SubDirectoryType::Bin: 839 if (VSLayout == ToolsetLayout::VS2017OrNewer) { 840 const bool HostIsX64 = 841 llvm::Triple(llvm::sys::getProcessTriple()).isArch64Bit(); 842 const char *const HostName = HostIsX64 ? "Hostx64" : "Hostx86"; 843 llvm::sys::path::append(Path, "bin", HostName, SubdirName); 844 } else { // OlderVS or DevDivInternal 845 llvm::sys::path::append(Path, "bin", SubdirName); 846 } 847 break; 848 case SubDirectoryType::Include: 849 llvm::sys::path::append(Path, IncludeName); 850 break; 851 case SubDirectoryType::Lib: 852 llvm::sys::path::append(Path, "lib", SubdirName); 853 break; 854 } 855 return std::string(Path.str()); 856} 857 858#ifdef _WIN32 859static bool readFullStringValue(HKEY hkey, const char *valueName, 860 std::string &value) { 861 std::wstring WideValueName; 862 if (!llvm::ConvertUTF8toWide(valueName, WideValueName)) 863 return false; 864 865 DWORD result = 0; 866 DWORD valueSize = 0; 867 DWORD type = 0; 868 // First just query for the required size. 869 result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, &type, NULL, 870 &valueSize); 871 if (result != ERROR_SUCCESS || type != REG_SZ || !valueSize) 872 return false; 873 std::vector<BYTE> buffer(valueSize); 874 result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, NULL, &buffer[0], 875 &valueSize); 876 if (result == ERROR_SUCCESS) { 877 std::wstring WideValue(reinterpret_cast<const wchar_t *>(buffer.data()), 878 valueSize / sizeof(wchar_t)); 879 if (valueSize && WideValue.back() == L'\0') { 880 WideValue.pop_back(); 881 } 882 // The destination buffer must be empty as an invariant of the conversion 883 // function; but this function is sometimes called in a loop that passes in 884 // the same buffer, however. Simply clear it out so we can overwrite it. 885 value.clear(); 886 return llvm::convertWideToUTF8(WideValue, value); 887 } 888 return false; 889} 890#endif 891 892/// Read registry string. 893/// This also supports a means to look for high-versioned keys by use 894/// of a $VERSION placeholder in the key path. 895/// $VERSION in the key path is a placeholder for the version number, 896/// causing the highest value path to be searched for and used. 897/// I.e. "SOFTWARE\\Microsoft\\VisualStudio\\$VERSION". 898/// There can be additional characters in the component. Only the numeric 899/// characters are compared. This function only searches HKLM. 900static bool getSystemRegistryString(const char *keyPath, const char *valueName, 901 std::string &value, std::string *phValue) { 902#ifndef _WIN32 903 return false; 904#else 905 HKEY hRootKey = HKEY_LOCAL_MACHINE; 906 HKEY hKey = NULL; 907 long lResult; 908 bool returnValue = false; 909 910 const char *placeHolder = strstr(keyPath, "$VERSION"); 911 std::string bestName; 912 // If we have a $VERSION placeholder, do the highest-version search. 913 if (placeHolder) { 914 const char *keyEnd = placeHolder - 1; 915 const char *nextKey = placeHolder; 916 // Find end of previous key. 917 while ((keyEnd > keyPath) && (*keyEnd != '\\')) 918 keyEnd--; 919 // Find end of key containing $VERSION. 920 while (*nextKey && (*nextKey != '\\')) 921 nextKey++; 922 size_t partialKeyLength = keyEnd - keyPath; 923 char partialKey[256]; 924 if (partialKeyLength >= sizeof(partialKey)) 925 partialKeyLength = sizeof(partialKey) - 1; 926 strncpy(partialKey, keyPath, partialKeyLength); 927 partialKey[partialKeyLength] = '\0'; 928 HKEY hTopKey = NULL; 929 lResult = RegOpenKeyExA(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY, 930 &hTopKey); 931 if (lResult == ERROR_SUCCESS) { 932 char keyName[256]; 933 double bestValue = 0.0; 934 DWORD index, size = sizeof(keyName) - 1; 935 for (index = 0; RegEnumKeyExA(hTopKey, index, keyName, &size, NULL, NULL, 936 NULL, NULL) == ERROR_SUCCESS; 937 index++) { 938 const char *sp = keyName; 939 while (*sp && !isDigit(*sp)) 940 sp++; 941 if (!*sp) 942 continue; 943 const char *ep = sp + 1; 944 while (*ep && (isDigit(*ep) || (*ep == '.'))) 945 ep++; 946 char numBuf[32]; 947 strncpy(numBuf, sp, sizeof(numBuf) - 1); 948 numBuf[sizeof(numBuf) - 1] = '\0'; 949 double dvalue = strtod(numBuf, NULL); 950 if (dvalue > bestValue) { 951 // Test that InstallDir is indeed there before keeping this index. 952 // Open the chosen key path remainder. 953 bestName = keyName; 954 // Append rest of key. 955 bestName.append(nextKey); 956 lResult = RegOpenKeyExA(hTopKey, bestName.c_str(), 0, 957 KEY_READ | KEY_WOW64_32KEY, &hKey); 958 if (lResult == ERROR_SUCCESS) { 959 if (readFullStringValue(hKey, valueName, value)) { 960 bestValue = dvalue; 961 if (phValue) 962 *phValue = bestName; 963 returnValue = true; 964 } 965 RegCloseKey(hKey); 966 } 967 } 968 size = sizeof(keyName) - 1; 969 } 970 RegCloseKey(hTopKey); 971 } 972 } else { 973 lResult = 974 RegOpenKeyExA(hRootKey, keyPath, 0, KEY_READ | KEY_WOW64_32KEY, &hKey); 975 if (lResult == ERROR_SUCCESS) { 976 if (readFullStringValue(hKey, valueName, value)) 977 returnValue = true; 978 if (phValue) 979 phValue->clear(); 980 RegCloseKey(hKey); 981 } 982 } 983 return returnValue; 984#endif // _WIN32 985} 986 987// Find the most recent version of Universal CRT or Windows 10 SDK. 988// vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include 989// directory by name and uses the last one of the list. 990// So we compare entry names lexicographically to find the greatest one. 991static bool getWindows10SDKVersionFromPath(llvm::vfs::FileSystem &VFS, 992 const std::string &SDKPath, 993 std::string &SDKVersion) { 994 llvm::SmallString<128> IncludePath(SDKPath); 995 llvm::sys::path::append(IncludePath, "Include"); 996 SDKVersion = getHighestNumericTupleInDirectory(VFS, IncludePath); 997 return !SDKVersion.empty(); 998} 999 1000static bool getWindowsSDKDirViaCommandLine(llvm::vfs::FileSystem &VFS, 1001 const ArgList &Args, 1002 std::string &Path, int &Major, 1003 std::string &Version) { 1004 if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkdir, 1005 options::OPT__SLASH_winsysroot)) { 1006 // Don't validate the input; trust the value supplied by the user. 1007 // The motivation is to prevent unnecessary file and registry access. 1008 llvm::VersionTuple SDKVersion; 1009 if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkversion)) 1010 SDKVersion.tryParse(A->getValue()); 1011 1012 if (A->getOption().getID() == options::OPT__SLASH_winsysroot) { 1013 llvm::SmallString<128> SDKPath(A->getValue()); 1014 llvm::sys::path::append(SDKPath, "Windows Kits"); 1015 if (!SDKVersion.empty()) 1016 llvm::sys::path::append(SDKPath, Twine(SDKVersion.getMajor())); 1017 else 1018 llvm::sys::path::append( 1019 SDKPath, getHighestNumericTupleInDirectory(VFS, SDKPath)); 1020 Path = std::string(SDKPath.str()); 1021 } else { 1022 Path = A->getValue(); 1023 } 1024 1025 if (!SDKVersion.empty()) { 1026 Major = SDKVersion.getMajor(); 1027 Version = SDKVersion.getAsString(); 1028 } else if (getWindows10SDKVersionFromPath(VFS, Path, Version)) { 1029 Major = 10; 1030 } 1031 return true; 1032 } 1033 return false; 1034} 1035 1036/// Get Windows SDK installation directory. 1037static bool getWindowsSDKDir(llvm::vfs::FileSystem &VFS, const ArgList &Args, 1038 std::string &Path, int &Major, 1039 std::string &WindowsSDKIncludeVersion, 1040 std::string &WindowsSDKLibVersion) { 1041 // Trust /winsdkdir and /winsdkversion if present. 1042 if (getWindowsSDKDirViaCommandLine(VFS, Args, Path, Major, 1043 WindowsSDKIncludeVersion)) { 1044 WindowsSDKLibVersion = WindowsSDKIncludeVersion; 1045 return true; 1046 } 1047 1048 // FIXME: Try env vars (%WindowsSdkDir%, %UCRTVersion%) before going to registry. 1049 1050 // Try the Windows registry. 1051 std::string RegistrySDKVersion; 1052 if (!getSystemRegistryString( 1053 "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION", 1054 "InstallationFolder", Path, &RegistrySDKVersion)) 1055 return false; 1056 if (Path.empty() || RegistrySDKVersion.empty()) 1057 return false; 1058 1059 WindowsSDKIncludeVersion.clear(); 1060 WindowsSDKLibVersion.clear(); 1061 Major = 0; 1062 std::sscanf(RegistrySDKVersion.c_str(), "v%d.", &Major); 1063 if (Major <= 7) 1064 return true; 1065 if (Major == 8) { 1066 // Windows SDK 8.x installs libraries in a folder whose names depend on the 1067 // version of the OS you're targeting. By default choose the newest, which 1068 // usually corresponds to the version of the OS you've installed the SDK on. 1069 const char *Tests[] = {"winv6.3", "win8", "win7"}; 1070 for (const char *Test : Tests) { 1071 llvm::SmallString<128> TestPath(Path); 1072 llvm::sys::path::append(TestPath, "Lib", Test); 1073 if (VFS.exists(TestPath)) { 1074 WindowsSDKLibVersion = Test; 1075 break; 1076 } 1077 } 1078 return !WindowsSDKLibVersion.empty(); 1079 } 1080 if (Major == 10) { 1081 if (!getWindows10SDKVersionFromPath(VFS, Path, WindowsSDKIncludeVersion)) 1082 return false; 1083 WindowsSDKLibVersion = WindowsSDKIncludeVersion; 1084 return true; 1085 } 1086 // Unsupported SDK version 1087 return false; 1088} 1089 1090// Gets the library path required to link against the Windows SDK. 1091bool MSVCToolChain::getWindowsSDKLibraryPath( 1092 const ArgList &Args, std::string &path) const { 1093 std::string sdkPath; 1094 int sdkMajor = 0; 1095 std::string windowsSDKIncludeVersion; 1096 std::string windowsSDKLibVersion; 1097 1098 path.clear(); 1099 if (!getWindowsSDKDir(getVFS(), Args, sdkPath, sdkMajor, 1100 windowsSDKIncludeVersion, windowsSDKLibVersion)) 1101 return false; 1102 1103 llvm::SmallString<128> libPath(sdkPath); 1104 llvm::sys::path::append(libPath, "Lib"); 1105 if (sdkMajor >= 8) { 1106 llvm::sys::path::append(libPath, windowsSDKLibVersion, "um", 1107 llvmArchToWindowsSDKArch(getArch())); 1108 } else { 1109 switch (getArch()) { 1110 // In Windows SDK 7.x, x86 libraries are directly in the Lib folder. 1111 case llvm::Triple::x86: 1112 break; 1113 case llvm::Triple::x86_64: 1114 llvm::sys::path::append(libPath, "x64"); 1115 break; 1116 case llvm::Triple::arm: 1117 // It is not necessary to link against Windows SDK 7.x when targeting ARM. 1118 return false; 1119 default: 1120 return false; 1121 } 1122 } 1123 1124 path = std::string(libPath.str()); 1125 return true; 1126} 1127 1128// Check if the Include path of a specified version of Visual Studio contains 1129// specific header files. If not, they are probably shipped with Universal CRT. 1130bool MSVCToolChain::useUniversalCRT() const { 1131 llvm::SmallString<128> TestPath( 1132 getSubDirectoryPath(SubDirectoryType::Include)); 1133 llvm::sys::path::append(TestPath, "stdlib.h"); 1134 return !getVFS().exists(TestPath); 1135} 1136 1137static bool getUniversalCRTSdkDir(llvm::vfs::FileSystem &VFS, 1138 const ArgList &Args, std::string &Path, 1139 std::string &UCRTVersion) { 1140 // If /winsdkdir is passed, use it as location for the UCRT too. 1141 // FIXME: Should there be a dedicated /ucrtdir to override /winsdkdir? 1142 int Major; 1143 if (getWindowsSDKDirViaCommandLine(VFS, Args, Path, Major, UCRTVersion)) 1144 return true; 1145 1146 // FIXME: Try env vars (%UniversalCRTSdkDir%, %UCRTVersion%) before going to 1147 // registry. 1148 1149 // vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry 1150 // for the specific key "KitsRoot10". So do we. 1151 if (!getSystemRegistryString( 1152 "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10", 1153 Path, nullptr)) 1154 return false; 1155 1156 return getWindows10SDKVersionFromPath(VFS, Path, UCRTVersion); 1157} 1158 1159bool MSVCToolChain::getUniversalCRTLibraryPath(const ArgList &Args, 1160 std::string &Path) const { 1161 std::string UniversalCRTSdkPath; 1162 std::string UCRTVersion; 1163 1164 Path.clear(); 1165 if (!getUniversalCRTSdkDir(getVFS(), Args, UniversalCRTSdkPath, UCRTVersion)) 1166 return false; 1167 1168 StringRef ArchName = llvmArchToWindowsSDKArch(getArch()); 1169 if (ArchName.empty()) 1170 return false; 1171 1172 llvm::SmallString<128> LibPath(UniversalCRTSdkPath); 1173 llvm::sys::path::append(LibPath, "Lib", UCRTVersion, "ucrt", ArchName); 1174 1175 Path = std::string(LibPath.str()); 1176 return true; 1177} 1178 1179static VersionTuple getMSVCVersionFromTriple(const llvm::Triple &Triple) { 1180 unsigned Major, Minor, Micro; 1181 Triple.getEnvironmentVersion(Major, Minor, Micro); 1182 if (Major || Minor || Micro) 1183 return VersionTuple(Major, Minor, Micro); 1184 return VersionTuple(); 1185} 1186 1187static VersionTuple getMSVCVersionFromExe(const std::string &BinDir) { 1188 VersionTuple Version; 1189#ifdef _WIN32 1190 SmallString<128> ClExe(BinDir); 1191 llvm::sys::path::append(ClExe, "cl.exe"); 1192 1193 std::wstring ClExeWide; 1194 if (!llvm::ConvertUTF8toWide(ClExe.c_str(), ClExeWide)) 1195 return Version; 1196 1197 const DWORD VersionSize = ::GetFileVersionInfoSizeW(ClExeWide.c_str(), 1198 nullptr); 1199 if (VersionSize == 0) 1200 return Version; 1201 1202 SmallVector<uint8_t, 4 * 1024> VersionBlock(VersionSize); 1203 if (!::GetFileVersionInfoW(ClExeWide.c_str(), 0, VersionSize, 1204 VersionBlock.data())) 1205 return Version; 1206 1207 VS_FIXEDFILEINFO *FileInfo = nullptr; 1208 UINT FileInfoSize = 0; 1209 if (!::VerQueryValueW(VersionBlock.data(), L"\\", 1210 reinterpret_cast<LPVOID *>(&FileInfo), &FileInfoSize) || 1211 FileInfoSize < sizeof(*FileInfo)) 1212 return Version; 1213 1214 const unsigned Major = (FileInfo->dwFileVersionMS >> 16) & 0xFFFF; 1215 const unsigned Minor = (FileInfo->dwFileVersionMS ) & 0xFFFF; 1216 const unsigned Micro = (FileInfo->dwFileVersionLS >> 16) & 0xFFFF; 1217 1218 Version = VersionTuple(Major, Minor, Micro); 1219#endif 1220 return Version; 1221} 1222 1223void MSVCToolChain::AddSystemIncludeWithSubfolder( 1224 const ArgList &DriverArgs, ArgStringList &CC1Args, 1225 const std::string &folder, const Twine &subfolder1, const Twine &subfolder2, 1226 const Twine &subfolder3) const { 1227 llvm::SmallString<128> path(folder); 1228 llvm::sys::path::append(path, subfolder1, subfolder2, subfolder3); 1229 addSystemInclude(DriverArgs, CC1Args, path); 1230} 1231 1232void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 1233 ArgStringList &CC1Args) const { 1234 if (DriverArgs.hasArg(options::OPT_nostdinc)) 1235 return; 1236 1237 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 1238 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, getDriver().ResourceDir, 1239 "include"); 1240 } 1241 1242 // Add %INCLUDE%-like directories from the -imsvc flag. 1243 for (const auto &Path : DriverArgs.getAllArgValues(options::OPT__SLASH_imsvc)) 1244 addSystemInclude(DriverArgs, CC1Args, Path); 1245 1246 if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 1247 return; 1248 1249 // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat. 1250 // Skip if the user expressly set a vctoolsdir 1251 if (!DriverArgs.getLastArg(options::OPT__SLASH_vctoolsdir, 1252 options::OPT__SLASH_winsysroot)) { 1253 if (llvm::Optional<std::string> cl_include_dir = 1254 llvm::sys::Process::GetEnv("INCLUDE")) { 1255 SmallVector<StringRef, 8> Dirs; 1256 StringRef(*cl_include_dir) 1257 .split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false); 1258 for (StringRef Dir : Dirs) 1259 addSystemInclude(DriverArgs, CC1Args, Dir); 1260 if (!Dirs.empty()) 1261 return; 1262 } 1263 } 1264 1265 // When built with access to the proper Windows APIs, try to actually find 1266 // the correct include paths first. 1267 if (!VCToolChainPath.empty()) { 1268 addSystemInclude(DriverArgs, CC1Args, 1269 getSubDirectoryPath(SubDirectoryType::Include)); 1270 addSystemInclude(DriverArgs, CC1Args, 1271 getSubDirectoryPath(SubDirectoryType::Include, "atlmfc")); 1272 1273 if (useUniversalCRT()) { 1274 std::string UniversalCRTSdkPath; 1275 std::string UCRTVersion; 1276 if (getUniversalCRTSdkDir(getVFS(), DriverArgs, UniversalCRTSdkPath, 1277 UCRTVersion)) { 1278 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath, 1279 "Include", UCRTVersion, "ucrt"); 1280 } 1281 } 1282 1283 std::string WindowsSDKDir; 1284 int major; 1285 std::string windowsSDKIncludeVersion; 1286 std::string windowsSDKLibVersion; 1287 if (getWindowsSDKDir(getVFS(), DriverArgs, WindowsSDKDir, major, 1288 windowsSDKIncludeVersion, windowsSDKLibVersion)) { 1289 if (major >= 8) { 1290 // Note: windowsSDKIncludeVersion is empty for SDKs prior to v10. 1291 // Anyway, llvm::sys::path::append is able to manage it. 1292 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 1293 "Include", windowsSDKIncludeVersion, 1294 "shared"); 1295 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 1296 "Include", windowsSDKIncludeVersion, 1297 "um"); 1298 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 1299 "Include", windowsSDKIncludeVersion, 1300 "winrt"); 1301 } else { 1302 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 1303 "Include"); 1304 } 1305 } 1306 1307 return; 1308 } 1309 1310#if defined(_WIN32) 1311 // As a fallback, select default install paths. 1312 // FIXME: Don't guess drives and paths like this on Windows. 1313 const StringRef Paths[] = { 1314 "C:/Program Files/Microsoft Visual Studio 10.0/VC/include", 1315 "C:/Program Files/Microsoft Visual Studio 9.0/VC/include", 1316 "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include", 1317 "C:/Program Files/Microsoft Visual Studio 8/VC/include", 1318 "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include" 1319 }; 1320 addSystemIncludes(DriverArgs, CC1Args, Paths); 1321#endif 1322} 1323 1324void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, 1325 ArgStringList &CC1Args) const { 1326 // FIXME: There should probably be logic here to find libc++ on Windows. 1327} 1328 1329VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D, 1330 const ArgList &Args) const { 1331 bool IsWindowsMSVC = getTriple().isWindowsMSVCEnvironment(); 1332 VersionTuple MSVT = ToolChain::computeMSVCVersion(D, Args); 1333 if (MSVT.empty()) 1334 MSVT = getMSVCVersionFromTriple(getTriple()); 1335 if (MSVT.empty() && IsWindowsMSVC) 1336 MSVT = getMSVCVersionFromExe(getSubDirectoryPath(SubDirectoryType::Bin)); 1337 if (MSVT.empty() && 1338 Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, 1339 IsWindowsMSVC)) { 1340 // -fms-compatibility-version=19.11 is default, aka 2017, 15.3 1341 MSVT = VersionTuple(19, 11); 1342 } 1343 return MSVT; 1344} 1345 1346std::string 1347MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args, 1348 types::ID InputType) const { 1349 // The MSVC version doesn't care about the architecture, even though it 1350 // may look at the triple internally. 1351 VersionTuple MSVT = computeMSVCVersion(/*D=*/nullptr, Args); 1352 MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().getValueOr(0), 1353 MSVT.getSubminor().getValueOr(0)); 1354 1355 // For the rest of the triple, however, a computed architecture name may 1356 // be needed. 1357 llvm::Triple Triple(ToolChain::ComputeEffectiveClangTriple(Args, InputType)); 1358 if (Triple.getEnvironment() == llvm::Triple::MSVC) { 1359 StringRef ObjFmt = Triple.getEnvironmentName().split('-').second; 1360 if (ObjFmt.empty()) 1361 Triple.setEnvironmentName((Twine("msvc") + MSVT.getAsString()).str()); 1362 else 1363 Triple.setEnvironmentName( 1364 (Twine("msvc") + MSVT.getAsString() + Twine('-') + ObjFmt).str()); 1365 } 1366 return Triple.getTriple(); 1367} 1368 1369SanitizerMask MSVCToolChain::getSupportedSanitizers() const { 1370 SanitizerMask Res = ToolChain::getSupportedSanitizers(); 1371 Res |= SanitizerKind::Address; 1372 Res |= SanitizerKind::PointerCompare; 1373 Res |= SanitizerKind::PointerSubtract; 1374 Res |= SanitizerKind::Fuzzer; 1375 Res |= SanitizerKind::FuzzerNoLink; 1376 Res &= ~SanitizerKind::CFIMFCall; 1377 return Res; 1378} 1379 1380static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL, 1381 bool SupportsForcingFramePointer, 1382 const char *ExpandChar, const OptTable &Opts) { 1383 assert(A->getOption().matches(options::OPT__SLASH_O)); 1384 1385 StringRef OptStr = A->getValue(); 1386 for (size_t I = 0, E = OptStr.size(); I != E; ++I) { 1387 const char &OptChar = *(OptStr.data() + I); 1388 switch (OptChar) { 1389 default: 1390 break; 1391 case '1': 1392 case '2': 1393 case 'x': 1394 case 'd': 1395 // Ignore /O[12xd] flags that aren't the last one on the command line. 1396 // Only the last one gets expanded. 1397 if (&OptChar != ExpandChar) { 1398 A->claim(); 1399 break; 1400 } 1401 if (OptChar == 'd') { 1402 DAL.AddFlagArg(A, Opts.getOption(options::OPT_O0)); 1403 } else { 1404 if (OptChar == '1') { 1405 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s"); 1406 } else if (OptChar == '2' || OptChar == 'x') { 1407 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin)); 1408 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2"); 1409 } 1410 if (SupportsForcingFramePointer && 1411 !DAL.hasArgNoClaim(options::OPT_fno_omit_frame_pointer)) 1412 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fomit_frame_pointer)); 1413 if (OptChar == '1' || OptChar == '2') 1414 DAL.AddFlagArg(A, Opts.getOption(options::OPT_ffunction_sections)); 1415 } 1416 break; 1417 case 'b': 1418 if (I + 1 != E && isdigit(OptStr[I + 1])) { 1419 switch (OptStr[I + 1]) { 1420 case '0': 1421 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_inline)); 1422 break; 1423 case '1': 1424 DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_hint_functions)); 1425 break; 1426 case '2': 1427 DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_functions)); 1428 break; 1429 } 1430 ++I; 1431 } 1432 break; 1433 case 'g': 1434 A->claim(); 1435 break; 1436 case 'i': 1437 if (I + 1 != E && OptStr[I + 1] == '-') { 1438 ++I; 1439 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin)); 1440 } else { 1441 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin)); 1442 } 1443 break; 1444 case 's': 1445 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s"); 1446 break; 1447 case 't': 1448 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2"); 1449 break; 1450 case 'y': { 1451 bool OmitFramePointer = true; 1452 if (I + 1 != E && OptStr[I + 1] == '-') { 1453 OmitFramePointer = false; 1454 ++I; 1455 } 1456 if (SupportsForcingFramePointer) { 1457 if (OmitFramePointer) 1458 DAL.AddFlagArg(A, 1459 Opts.getOption(options::OPT_fomit_frame_pointer)); 1460 else 1461 DAL.AddFlagArg( 1462 A, Opts.getOption(options::OPT_fno_omit_frame_pointer)); 1463 } else { 1464 // Don't warn about /Oy- in x86-64 builds (where 1465 // SupportsForcingFramePointer is false). The flag having no effect 1466 // there is a compiler-internal optimization, and people shouldn't have 1467 // to special-case their build files for x86-64 clang-cl. 1468 A->claim(); 1469 } 1470 break; 1471 } 1472 } 1473 } 1474} 1475 1476static void TranslateDArg(Arg *A, llvm::opt::DerivedArgList &DAL, 1477 const OptTable &Opts) { 1478 assert(A->getOption().matches(options::OPT_D)); 1479 1480 StringRef Val = A->getValue(); 1481 size_t Hash = Val.find('#'); 1482 if (Hash == StringRef::npos || Hash > Val.find('=')) { 1483 DAL.append(A); 1484 return; 1485 } 1486 1487 std::string NewVal = std::string(Val); 1488 NewVal[Hash] = '='; 1489 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_D), NewVal); 1490} 1491 1492llvm::opt::DerivedArgList * 1493MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args, 1494 StringRef BoundArch, 1495 Action::OffloadKind OFK) const { 1496 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); 1497 const OptTable &Opts = getDriver().getOpts(); 1498 1499 // /Oy and /Oy- don't have an effect on X86-64 1500 bool SupportsForcingFramePointer = getArch() != llvm::Triple::x86_64; 1501 1502 // The -O[12xd] flag actually expands to several flags. We must desugar the 1503 // flags so that options embedded can be negated. For example, the '-O2' flag 1504 // enables '-Oy'. Expanding '-O2' into its constituent flags allows us to 1505 // correctly handle '-O2 -Oy-' where the trailing '-Oy-' disables a single 1506 // aspect of '-O2'. 1507 // 1508 // Note that this expansion logic only applies to the *last* of '[12xd]'. 1509 1510 // First step is to search for the character we'd like to expand. 1511 const char *ExpandChar = nullptr; 1512 for (Arg *A : Args.filtered(options::OPT__SLASH_O)) { 1513 StringRef OptStr = A->getValue(); 1514 for (size_t I = 0, E = OptStr.size(); I != E; ++I) { 1515 char OptChar = OptStr[I]; 1516 char PrevChar = I > 0 ? OptStr[I - 1] : '0'; 1517 if (PrevChar == 'b') { 1518 // OptChar does not expand; it's an argument to the previous char. 1519 continue; 1520 } 1521 if (OptChar == '1' || OptChar == '2' || OptChar == 'x' || OptChar == 'd') 1522 ExpandChar = OptStr.data() + I; 1523 } 1524 } 1525 1526 for (Arg *A : Args) { 1527 if (A->getOption().matches(options::OPT__SLASH_O)) { 1528 // The -O flag actually takes an amalgam of other options. For example, 1529 // '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'. 1530 TranslateOptArg(A, *DAL, SupportsForcingFramePointer, ExpandChar, Opts); 1531 } else if (A->getOption().matches(options::OPT_D)) { 1532 // Translate -Dfoo#bar into -Dfoo=bar. 1533 TranslateDArg(A, *DAL, Opts); 1534 } else if (OFK != Action::OFK_HIP) { 1535 // HIP Toolchain translates input args by itself. 1536 DAL->append(A); 1537 } 1538 } 1539 1540 return DAL; 1541} 1542