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