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