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