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