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