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