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