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