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