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 using namespace clang::driver; 44 using namespace clang::driver::toolchains; 45 using namespace clang::driver::tools; 46 using namespace clang; 47 using namespace llvm::opt; 48 49 static bool canExecute(llvm::vfs::FileSystem &VFS, StringRef Path) { 50 auto Status = VFS.status(Path); 51 if (!Status) 52 return false; 53 return (Status->getPermissions() & llvm::sys::fs::perms::all_exe) != 0; 54 } 55 56 // Try to find Exe from a Visual Studio distribution. This first tries to find 57 // an installed copy of Visual Studio and, failing that, looks in the PATH, 58 // making sure that whatever executable that's found is not a same-named exe 59 // from clang itself to prevent clang from falling back to itself. 60 static std::string FindVisualStudioExecutable(const ToolChain &TC, 61 const char *Exe) { 62 const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC); 63 SmallString<128> FilePath( 64 MSVC.getSubDirectoryPath(llvm::SubDirectoryType::Bin)); 65 llvm::sys::path::append(FilePath, Exe); 66 return std::string(canExecute(TC.getVFS(), FilePath) ? FilePath.str() : Exe); 67 } 68 69 void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, 70 const InputInfo &Output, 71 const InputInfoList &Inputs, 72 const ArgList &Args, 73 const char *LinkingOutput) const { 74 ArgStringList CmdArgs; 75 76 auto &TC = static_cast<const toolchains::MSVCToolChain &>(getToolChain()); 77 78 assert((Output.isFilename() || Output.isNothing()) && "invalid output"); 79 if (Output.isFilename()) 80 CmdArgs.push_back( 81 Args.MakeArgString(std::string("-out:") + Output.getFilename())); 82 83 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) && 84 !C.getDriver().IsCLMode()) { 85 CmdArgs.push_back("-defaultlib:libcmt"); 86 CmdArgs.push_back("-defaultlib:oldnames"); 87 } 88 89 // If the VC environment hasn't been configured (perhaps because the user 90 // did not run vcvarsall), try to build a consistent link environment. If 91 // the environment variable is set however, assume the user knows what 92 // they're doing. If the user passes /vctoolsdir or /winsdkdir, trust that 93 // over env vars. 94 if (const Arg *A = Args.getLastArg(options::OPT__SLASH_diasdkdir, 95 options::OPT__SLASH_winsysroot)) { 96 // cl.exe doesn't find the DIA SDK automatically, so this too requires 97 // explicit flags and doesn't automatically look in "DIA SDK" relative 98 // to the path we found for VCToolChainPath. 99 llvm::SmallString<128> DIAPath(A->getValue()); 100 if (A->getOption().getID() == options::OPT__SLASH_winsysroot) 101 llvm::sys::path::append(DIAPath, "DIA SDK"); 102 103 // The DIA SDK always uses the legacy vc arch, even in new MSVC versions. 104 llvm::sys::path::append(DIAPath, "lib", 105 llvm::archToLegacyVCArch(TC.getArch())); 106 CmdArgs.push_back(Args.MakeArgString(Twine("-libpath:") + DIAPath)); 107 } 108 if (!llvm::sys::Process::GetEnv("LIB") || 109 Args.getLastArg(options::OPT__SLASH_vctoolsdir, 110 options::OPT__SLASH_winsysroot)) { 111 CmdArgs.push_back(Args.MakeArgString( 112 Twine("-libpath:") + 113 TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib))); 114 CmdArgs.push_back(Args.MakeArgString( 115 Twine("-libpath:") + 116 TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib, "atlmfc"))); 117 } 118 if (!llvm::sys::Process::GetEnv("LIB") || 119 Args.getLastArg(options::OPT__SLASH_winsdkdir, 120 options::OPT__SLASH_winsysroot)) { 121 if (TC.useUniversalCRT()) { 122 std::string UniversalCRTLibPath; 123 if (TC.getUniversalCRTLibraryPath(Args, UniversalCRTLibPath)) 124 CmdArgs.push_back( 125 Args.MakeArgString(Twine("-libpath:") + UniversalCRTLibPath)); 126 } 127 std::string WindowsSdkLibPath; 128 if (TC.getWindowsSDKLibraryPath(Args, WindowsSdkLibPath)) 129 CmdArgs.push_back( 130 Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath)); 131 } 132 133 // Add the compiler-rt library directories to libpath if they exist to help 134 // the linker find the various sanitizer, builtin, and profiling runtimes. 135 for (const auto &LibPath : TC.getLibraryPaths()) { 136 if (TC.getVFS().exists(LibPath)) 137 CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath)); 138 } 139 auto CRTPath = TC.getCompilerRTPath(); 140 if (TC.getVFS().exists(CRTPath)) 141 CmdArgs.push_back(Args.MakeArgString("-libpath:" + CRTPath)); 142 143 if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L)) 144 for (const auto &LibPath : Args.getAllArgValues(options::OPT_L)) 145 CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath)); 146 147 CmdArgs.push_back("-nologo"); 148 149 if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7)) 150 CmdArgs.push_back("-debug"); 151 152 // If we specify /hotpatch, let the linker add padding in front of each 153 // function, like MSVC does. 154 if (Args.hasArg(options::OPT_fms_hotpatch, options::OPT__SLASH_hotpatch)) 155 CmdArgs.push_back("-functionpadmin"); 156 157 // Pass on /Brepro if it was passed to the compiler. 158 // Note that /Brepro maps to -mno-incremental-linker-compatible. 159 bool DefaultIncrementalLinkerCompatible = 160 C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment(); 161 if (!Args.hasFlag(options::OPT_mincremental_linker_compatible, 162 options::OPT_mno_incremental_linker_compatible, 163 DefaultIncrementalLinkerCompatible)) 164 CmdArgs.push_back("-Brepro"); 165 166 bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd, 167 options::OPT_shared); 168 if (DLL) { 169 CmdArgs.push_back(Args.MakeArgString("-dll")); 170 171 SmallString<128> ImplibName(Output.getFilename()); 172 llvm::sys::path::replace_extension(ImplibName, "lib"); 173 CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName)); 174 } 175 176 if (TC.getSanitizerArgs(Args).needsFuzzer()) { 177 if (!Args.hasArg(options::OPT_shared)) 178 CmdArgs.push_back( 179 Args.MakeArgString(std::string("-wholearchive:") + 180 TC.getCompilerRTArgString(Args, "fuzzer"))); 181 CmdArgs.push_back(Args.MakeArgString("-debug")); 182 // Prevent the linker from padding sections we use for instrumentation 183 // arrays. 184 CmdArgs.push_back(Args.MakeArgString("-incremental:no")); 185 } 186 187 if (TC.getSanitizerArgs(Args).needsAsanRt()) { 188 CmdArgs.push_back(Args.MakeArgString("-debug")); 189 CmdArgs.push_back(Args.MakeArgString("-incremental:no")); 190 if (TC.getSanitizerArgs(Args).needsSharedRt() || 191 Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) { 192 for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"}) 193 CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib)); 194 // Make sure the dynamic runtime thunk is not optimized out at link time 195 // to ensure proper SEH handling. 196 CmdArgs.push_back(Args.MakeArgString( 197 TC.getArch() == llvm::Triple::x86 198 ? "-include:___asan_seh_interceptor" 199 : "-include:__asan_seh_interceptor")); 200 // Make sure the linker consider all object files from the dynamic runtime 201 // thunk. 202 CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") + 203 TC.getCompilerRT(Args, "asan_dynamic_runtime_thunk"))); 204 } else if (DLL) { 205 CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk")); 206 } else { 207 for (const auto &Lib : {"asan", "asan_cxx"}) { 208 CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib)); 209 // Make sure the linker consider all object files from the static lib. 210 // This is necessary because instrumented dlls need access to all the 211 // interface exported by the static lib in the main executable. 212 CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") + 213 TC.getCompilerRT(Args, Lib))); 214 } 215 } 216 } 217 218 Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link); 219 220 // Control Flow Guard checks 221 if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) { 222 StringRef GuardArgs = A->getValue(); 223 if (GuardArgs.equals_insensitive("cf") || 224 GuardArgs.equals_insensitive("cf,nochecks")) { 225 // MSVC doesn't yet support the "nochecks" modifier. 226 CmdArgs.push_back("-guard:cf"); 227 } else if (GuardArgs.equals_insensitive("cf-")) { 228 CmdArgs.push_back("-guard:cf-"); 229 } else if (GuardArgs.equals_insensitive("ehcont")) { 230 CmdArgs.push_back("-guard:ehcont"); 231 } else if (GuardArgs.equals_insensitive("ehcont-")) { 232 CmdArgs.push_back("-guard:ehcont-"); 233 } 234 } 235 236 if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, 237 options::OPT_fno_openmp, false)) { 238 CmdArgs.push_back("-nodefaultlib:vcomp.lib"); 239 CmdArgs.push_back("-nodefaultlib:vcompd.lib"); 240 CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") + 241 TC.getDriver().Dir + "/../lib")); 242 switch (TC.getDriver().getOpenMPRuntime(Args)) { 243 case Driver::OMPRT_OMP: 244 CmdArgs.push_back("-defaultlib:libomp.lib"); 245 break; 246 case Driver::OMPRT_IOMP5: 247 CmdArgs.push_back("-defaultlib:libiomp5md.lib"); 248 break; 249 case Driver::OMPRT_GOMP: 250 break; 251 case Driver::OMPRT_Unknown: 252 // Already diagnosed. 253 break; 254 } 255 } 256 257 // Add compiler-rt lib in case if it was explicitly 258 // specified as an argument for --rtlib option. 259 if (!Args.hasArg(options::OPT_nostdlib)) { 260 AddRunTimeLibs(TC, TC.getDriver(), CmdArgs, Args); 261 } 262 263 // Add filenames, libraries, and other linker inputs. 264 for (const auto &Input : Inputs) { 265 if (Input.isFilename()) { 266 CmdArgs.push_back(Input.getFilename()); 267 continue; 268 } 269 270 const Arg &A = Input.getInputArg(); 271 272 // Render -l options differently for the MSVC linker. 273 if (A.getOption().matches(options::OPT_l)) { 274 StringRef Lib = A.getValue(); 275 const char *LinkLibArg; 276 if (Lib.endswith(".lib")) 277 LinkLibArg = Args.MakeArgString(Lib); 278 else 279 LinkLibArg = Args.MakeArgString(Lib + ".lib"); 280 CmdArgs.push_back(LinkLibArg); 281 continue; 282 } 283 284 // Otherwise, this is some other kind of linker input option like -Wl, -z, 285 // or -L. Render it, even if MSVC doesn't understand it. 286 A.renderAsInput(Args, CmdArgs); 287 } 288 289 addHIPRuntimeLibArgs(TC, Args, CmdArgs); 290 291 TC.addProfileRTLibs(Args, CmdArgs); 292 293 std::vector<const char *> Environment; 294 295 // We need to special case some linker paths. In the case of lld, we need to 296 // translate 'lld' into 'lld-link', and in the case of the regular msvc 297 // linker, we need to use a special search algorithm. 298 llvm::SmallString<128> linkPath; 299 StringRef Linker 300 = Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER); 301 if (Linker.empty()) 302 Linker = "link"; 303 if (Linker.equals_insensitive("lld")) 304 Linker = "lld-link"; 305 306 if (Linker.equals_insensitive("link")) { 307 // If we're using the MSVC linker, it's not sufficient to just use link 308 // from the program PATH, because other environments like GnuWin32 install 309 // their own link.exe which may come first. 310 linkPath = FindVisualStudioExecutable(TC, "link.exe"); 311 312 if (!TC.FoundMSVCInstall() && !canExecute(TC.getVFS(), linkPath)) { 313 llvm::SmallString<128> ClPath; 314 ClPath = TC.GetProgramPath("cl.exe"); 315 if (canExecute(TC.getVFS(), ClPath)) { 316 linkPath = llvm::sys::path::parent_path(ClPath); 317 llvm::sys::path::append(linkPath, "link.exe"); 318 if (!canExecute(TC.getVFS(), linkPath)) 319 C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found); 320 } else { 321 C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found); 322 } 323 } 324 325 #ifdef _WIN32 326 // When cross-compiling with VS2017 or newer, link.exe expects to have 327 // its containing bin directory at the top of PATH, followed by the 328 // native target bin directory. 329 // e.g. when compiling for x86 on an x64 host, PATH should start with: 330 // /bin/Hostx64/x86;/bin/Hostx64/x64 331 // This doesn't attempt to handle llvm::ToolsetLayout::DevDivInternal. 332 if (TC.getIsVS2017OrNewer() && 333 llvm::Triple(llvm::sys::getProcessTriple()).getArch() != TC.getArch()) { 334 auto HostArch = llvm::Triple(llvm::sys::getProcessTriple()).getArch(); 335 336 auto EnvBlockWide = 337 std::unique_ptr<wchar_t[], decltype(&FreeEnvironmentStringsW)>( 338 GetEnvironmentStringsW(), FreeEnvironmentStringsW); 339 if (!EnvBlockWide) 340 goto SkipSettingEnvironment; 341 342 size_t EnvCount = 0; 343 size_t EnvBlockLen = 0; 344 while (EnvBlockWide[EnvBlockLen] != L'\0') { 345 ++EnvCount; 346 EnvBlockLen += std::wcslen(&EnvBlockWide[EnvBlockLen]) + 347 1 /*string null-terminator*/; 348 } 349 ++EnvBlockLen; // add the block null-terminator 350 351 std::string EnvBlock; 352 if (!llvm::convertUTF16ToUTF8String( 353 llvm::ArrayRef<char>(reinterpret_cast<char *>(EnvBlockWide.get()), 354 EnvBlockLen * sizeof(EnvBlockWide[0])), 355 EnvBlock)) 356 goto SkipSettingEnvironment; 357 358 Environment.reserve(EnvCount); 359 360 // Now loop over each string in the block and copy them into the 361 // environment vector, adjusting the PATH variable as needed when we 362 // find it. 363 for (const char *Cursor = EnvBlock.data(); *Cursor != '\0';) { 364 llvm::StringRef EnvVar(Cursor); 365 if (EnvVar.startswith_insensitive("path=")) { 366 constexpr size_t PrefixLen = 5; // strlen("path=") 367 Environment.push_back(Args.MakeArgString( 368 EnvVar.substr(0, PrefixLen) + 369 TC.getSubDirectoryPath(llvm::SubDirectoryType::Bin) + 370 llvm::Twine(llvm::sys::EnvPathSeparator) + 371 TC.getSubDirectoryPath(llvm::SubDirectoryType::Bin, HostArch) + 372 (EnvVar.size() > PrefixLen 373 ? llvm::Twine(llvm::sys::EnvPathSeparator) + 374 EnvVar.substr(PrefixLen) 375 : ""))); 376 } else { 377 Environment.push_back(Args.MakeArgString(EnvVar)); 378 } 379 Cursor += EnvVar.size() + 1 /*null-terminator*/; 380 } 381 } 382 SkipSettingEnvironment:; 383 #endif 384 } else { 385 linkPath = TC.GetProgramPath(Linker.str().c_str()); 386 } 387 388 auto LinkCmd = std::make_unique<Command>( 389 JA, *this, ResponseFileSupport::AtFileUTF16(), 390 Args.MakeArgString(linkPath), CmdArgs, Inputs, Output); 391 if (!Environment.empty()) 392 LinkCmd->setEnvironment(Environment); 393 C.addCommand(std::move(LinkCmd)); 394 } 395 396 MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple, 397 const ArgList &Args) 398 : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args), 399 RocmInstallation(D, Triple, Args) { 400 getProgramPaths().push_back(getDriver().getInstalledDir()); 401 if (getDriver().getInstalledDir() != getDriver().Dir) 402 getProgramPaths().push_back(getDriver().Dir); 403 404 Optional<llvm::StringRef> VCToolsDir, VCToolsVersion; 405 if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir)) 406 VCToolsDir = A->getValue(); 407 if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsversion)) 408 VCToolsVersion = A->getValue(); 409 if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkdir)) 410 WinSdkDir = A->getValue(); 411 if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkversion)) 412 WinSdkVersion = A->getValue(); 413 if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsysroot)) 414 WinSysRoot = A->getValue(); 415 416 // Check the command line first, that's the user explicitly telling us what to 417 // use. Check the environment next, in case we're being invoked from a VS 418 // command prompt. Failing that, just try to find the newest Visual Studio 419 // version we can and use its default VC toolchain. 420 llvm::findVCToolChainViaCommandLine(getVFS(), VCToolsDir, VCToolsVersion, 421 WinSysRoot, VCToolChainPath, VSLayout) || 422 llvm::findVCToolChainViaEnvironment(getVFS(), VCToolChainPath, 423 VSLayout) || 424 llvm::findVCToolChainViaSetupConfig(getVFS(), VCToolChainPath, 425 VSLayout) || 426 llvm::findVCToolChainViaRegistry(VCToolChainPath, VSLayout); 427 } 428 429 Tool *MSVCToolChain::buildLinker() const { 430 return new tools::visualstudio::Linker(*this); 431 } 432 433 Tool *MSVCToolChain::buildAssembler() const { 434 if (getTriple().isOSBinFormatMachO()) 435 return new tools::darwin::Assembler(*this); 436 getDriver().Diag(clang::diag::err_no_external_assembler); 437 return nullptr; 438 } 439 440 bool MSVCToolChain::IsIntegratedAssemblerDefault() const { 441 return true; 442 } 443 444 bool MSVCToolChain::IsUnwindTablesDefault(const ArgList &Args) const { 445 // Don't emit unwind tables by default for MachO targets. 446 if (getTriple().isOSBinFormatMachO()) 447 return false; 448 449 // All non-x86_32 Windows targets require unwind tables. However, LLVM 450 // doesn't know how to generate them for all targets, so only enable 451 // the ones that are actually implemented. 452 return getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::arm || 453 getArch() == llvm::Triple::thumb || getArch() == llvm::Triple::aarch64; 454 } 455 456 bool MSVCToolChain::isPICDefault() const { 457 return getArch() == llvm::Triple::x86_64 || 458 getArch() == llvm::Triple::aarch64; 459 } 460 461 bool MSVCToolChain::isPIEDefault(const llvm::opt::ArgList &Args) const { 462 return false; 463 } 464 465 bool MSVCToolChain::isPICDefaultForced() const { 466 return getArch() == llvm::Triple::x86_64 || 467 getArch() == llvm::Triple::aarch64; 468 } 469 470 void MSVCToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs, 471 ArgStringList &CC1Args) const { 472 CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args); 473 } 474 475 void MSVCToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs, 476 ArgStringList &CC1Args) const { 477 RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args); 478 } 479 480 void MSVCToolChain::AddHIPRuntimeLibArgs(const ArgList &Args, 481 ArgStringList &CmdArgs) const { 482 CmdArgs.append({Args.MakeArgString(StringRef("-libpath:") + 483 RocmInstallation.getLibPath()), 484 "amdhip64.lib"}); 485 } 486 487 void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const { 488 CudaInstallation.print(OS); 489 RocmInstallation.print(OS); 490 } 491 492 std::string 493 MSVCToolChain::getSubDirectoryPath(llvm::SubDirectoryType Type, 494 llvm::StringRef SubdirParent) const { 495 return llvm::getSubDirectoryPath(Type, VSLayout, VCToolChainPath, getArch(), 496 SubdirParent); 497 } 498 499 std::string 500 MSVCToolChain::getSubDirectoryPath(llvm::SubDirectoryType Type, 501 llvm::Triple::ArchType TargetArch) const { 502 return llvm::getSubDirectoryPath(Type, VSLayout, VCToolChainPath, TargetArch, 503 ""); 504 } 505 506 // Find the most recent version of Universal CRT or Windows 10 SDK. 507 // vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include 508 // directory by name and uses the last one of the list. 509 // So we compare entry names lexicographically to find the greatest one. 510 // Gets the library path required to link against the Windows SDK. 511 bool MSVCToolChain::getWindowsSDKLibraryPath(const ArgList &Args, 512 std::string &path) const { 513 std::string sdkPath; 514 int sdkMajor = 0; 515 std::string windowsSDKIncludeVersion; 516 std::string windowsSDKLibVersion; 517 518 path.clear(); 519 if (!llvm::getWindowsSDKDir(getVFS(), WinSdkDir, WinSdkVersion, WinSysRoot, 520 sdkPath, sdkMajor, windowsSDKIncludeVersion, 521 windowsSDKLibVersion)) 522 return false; 523 524 llvm::SmallString<128> libPath(sdkPath); 525 llvm::sys::path::append(libPath, "Lib"); 526 if (sdkMajor >= 8) 527 llvm::sys::path::append(libPath, windowsSDKLibVersion, "um"); 528 return llvm::appendArchToWindowsSDKLibPath(sdkMajor, libPath, getArch(), 529 path); 530 } 531 532 bool MSVCToolChain::useUniversalCRT() const { 533 return llvm::useUniversalCRT(VSLayout, VCToolChainPath, getArch(), getVFS()); 534 } 535 536 bool MSVCToolChain::getUniversalCRTLibraryPath(const ArgList &Args, 537 std::string &Path) const { 538 std::string UniversalCRTSdkPath; 539 std::string UCRTVersion; 540 541 Path.clear(); 542 if (!llvm::getUniversalCRTSdkDir(getVFS(), WinSdkDir, WinSdkVersion, 543 WinSysRoot, UniversalCRTSdkPath, 544 UCRTVersion)) 545 return false; 546 547 StringRef ArchName = llvm::archToWindowsSDKArch(getArch()); 548 if (ArchName.empty()) 549 return false; 550 551 llvm::SmallString<128> LibPath(UniversalCRTSdkPath); 552 llvm::sys::path::append(LibPath, "Lib", UCRTVersion, "ucrt", ArchName); 553 554 Path = std::string(LibPath.str()); 555 return true; 556 } 557 558 static VersionTuple getMSVCVersionFromExe(const std::string &BinDir) { 559 VersionTuple Version; 560 #ifdef _WIN32 561 SmallString<128> ClExe(BinDir); 562 llvm::sys::path::append(ClExe, "cl.exe"); 563 564 std::wstring ClExeWide; 565 if (!llvm::ConvertUTF8toWide(ClExe.c_str(), ClExeWide)) 566 return Version; 567 568 const DWORD VersionSize = ::GetFileVersionInfoSizeW(ClExeWide.c_str(), 569 nullptr); 570 if (VersionSize == 0) 571 return Version; 572 573 SmallVector<uint8_t, 4 * 1024> VersionBlock(VersionSize); 574 if (!::GetFileVersionInfoW(ClExeWide.c_str(), 0, VersionSize, 575 VersionBlock.data())) 576 return Version; 577 578 VS_FIXEDFILEINFO *FileInfo = nullptr; 579 UINT FileInfoSize = 0; 580 if (!::VerQueryValueW(VersionBlock.data(), L"\\", 581 reinterpret_cast<LPVOID *>(&FileInfo), &FileInfoSize) || 582 FileInfoSize < sizeof(*FileInfo)) 583 return Version; 584 585 const unsigned Major = (FileInfo->dwFileVersionMS >> 16) & 0xFFFF; 586 const unsigned Minor = (FileInfo->dwFileVersionMS ) & 0xFFFF; 587 const unsigned Micro = (FileInfo->dwFileVersionLS >> 16) & 0xFFFF; 588 589 Version = VersionTuple(Major, Minor, Micro); 590 #endif 591 return Version; 592 } 593 594 void MSVCToolChain::AddSystemIncludeWithSubfolder( 595 const ArgList &DriverArgs, ArgStringList &CC1Args, 596 const std::string &folder, const Twine &subfolder1, const Twine &subfolder2, 597 const Twine &subfolder3) const { 598 llvm::SmallString<128> path(folder); 599 llvm::sys::path::append(path, subfolder1, subfolder2, subfolder3); 600 addSystemInclude(DriverArgs, CC1Args, path); 601 } 602 603 void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 604 ArgStringList &CC1Args) const { 605 if (DriverArgs.hasArg(options::OPT_nostdinc)) 606 return; 607 608 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 609 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, getDriver().ResourceDir, 610 "include"); 611 } 612 613 // Add %INCLUDE%-like directories from the -imsvc flag. 614 for (const auto &Path : DriverArgs.getAllArgValues(options::OPT__SLASH_imsvc)) 615 addSystemInclude(DriverArgs, CC1Args, Path); 616 617 auto AddSystemIncludesFromEnv = [&](StringRef Var) -> bool { 618 if (auto Val = llvm::sys::Process::GetEnv(Var)) { 619 SmallVector<StringRef, 8> Dirs; 620 StringRef(*Val).split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false); 621 if (!Dirs.empty()) { 622 addSystemIncludes(DriverArgs, CC1Args, Dirs); 623 return true; 624 } 625 } 626 return false; 627 }; 628 629 // Add %INCLUDE%-like dirs via /external:env: flags. 630 for (const auto &Var : 631 DriverArgs.getAllArgValues(options::OPT__SLASH_external_env)) { 632 AddSystemIncludesFromEnv(Var); 633 } 634 635 // Add DIA SDK include if requested. 636 if (const Arg *A = DriverArgs.getLastArg(options::OPT__SLASH_diasdkdir, 637 options::OPT__SLASH_winsysroot)) { 638 // cl.exe doesn't find the DIA SDK automatically, so this too requires 639 // explicit flags and doesn't automatically look in "DIA SDK" relative 640 // to the path we found for VCToolChainPath. 641 llvm::SmallString<128> DIASDKPath(A->getValue()); 642 if (A->getOption().getID() == options::OPT__SLASH_winsysroot) 643 llvm::sys::path::append(DIASDKPath, "DIA SDK"); 644 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, std::string(DIASDKPath), 645 "include"); 646 } 647 648 if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 649 return; 650 651 // Honor %INCLUDE% and %EXTERNAL_INCLUDE%. It should have essential search 652 // paths set by vcvarsall.bat. Skip if the user expressly set a vctoolsdir. 653 if (!DriverArgs.getLastArg(options::OPT__SLASH_vctoolsdir, 654 options::OPT__SLASH_winsysroot)) { 655 bool Found = AddSystemIncludesFromEnv("INCLUDE"); 656 Found |= AddSystemIncludesFromEnv("EXTERNAL_INCLUDE"); 657 if (Found) 658 return; 659 } 660 661 // When built with access to the proper Windows APIs, try to actually find 662 // the correct include paths first. 663 if (!VCToolChainPath.empty()) { 664 addSystemInclude(DriverArgs, CC1Args, 665 getSubDirectoryPath(llvm::SubDirectoryType::Include)); 666 addSystemInclude( 667 DriverArgs, CC1Args, 668 getSubDirectoryPath(llvm::SubDirectoryType::Include, "atlmfc")); 669 670 if (useUniversalCRT()) { 671 std::string UniversalCRTSdkPath; 672 std::string UCRTVersion; 673 if (llvm::getUniversalCRTSdkDir(getVFS(), WinSdkDir, WinSdkVersion, 674 WinSysRoot, UniversalCRTSdkPath, 675 UCRTVersion)) { 676 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath, 677 "Include", UCRTVersion, "ucrt"); 678 } 679 } 680 681 std::string WindowsSDKDir; 682 int major = 0; 683 std::string windowsSDKIncludeVersion; 684 std::string windowsSDKLibVersion; 685 if (llvm::getWindowsSDKDir(getVFS(), WinSdkDir, WinSdkVersion, WinSysRoot, 686 WindowsSDKDir, major, windowsSDKIncludeVersion, 687 windowsSDKLibVersion)) { 688 if (major >= 8) { 689 // Note: windowsSDKIncludeVersion is empty for SDKs prior to v10. 690 // Anyway, llvm::sys::path::append is able to manage it. 691 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 692 "Include", windowsSDKIncludeVersion, 693 "shared"); 694 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 695 "Include", windowsSDKIncludeVersion, 696 "um"); 697 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 698 "Include", windowsSDKIncludeVersion, 699 "winrt"); 700 if (major >= 10) { 701 llvm::VersionTuple Tuple; 702 if (!Tuple.tryParse(windowsSDKIncludeVersion) && 703 Tuple.getSubminor().getValueOr(0) >= 17134) { 704 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 705 "Include", windowsSDKIncludeVersion, 706 "cppwinrt"); 707 } 708 } 709 } else { 710 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 711 "Include"); 712 } 713 } 714 715 return; 716 } 717 718 #if defined(_WIN32) 719 // As a fallback, select default install paths. 720 // FIXME: Don't guess drives and paths like this on Windows. 721 const StringRef Paths[] = { 722 "C:/Program Files/Microsoft Visual Studio 10.0/VC/include", 723 "C:/Program Files/Microsoft Visual Studio 9.0/VC/include", 724 "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include", 725 "C:/Program Files/Microsoft Visual Studio 8/VC/include", 726 "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include" 727 }; 728 addSystemIncludes(DriverArgs, CC1Args, Paths); 729 #endif 730 } 731 732 void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, 733 ArgStringList &CC1Args) const { 734 // FIXME: There should probably be logic here to find libc++ on Windows. 735 } 736 737 VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D, 738 const ArgList &Args) const { 739 bool IsWindowsMSVC = getTriple().isWindowsMSVCEnvironment(); 740 VersionTuple MSVT = ToolChain::computeMSVCVersion(D, Args); 741 if (MSVT.empty()) 742 MSVT = getTriple().getEnvironmentVersion(); 743 if (MSVT.empty() && IsWindowsMSVC) 744 MSVT = 745 getMSVCVersionFromExe(getSubDirectoryPath(llvm::SubDirectoryType::Bin)); 746 if (MSVT.empty() && 747 Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, 748 IsWindowsMSVC)) { 749 // -fms-compatibility-version=19.20 is default, aka 2019, 16.x 750 MSVT = VersionTuple(19, 20); 751 } 752 return MSVT; 753 } 754 755 std::string 756 MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args, 757 types::ID InputType) const { 758 // The MSVC version doesn't care about the architecture, even though it 759 // may look at the triple internally. 760 VersionTuple MSVT = computeMSVCVersion(/*D=*/nullptr, Args); 761 MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().getValueOr(0), 762 MSVT.getSubminor().getValueOr(0)); 763 764 // For the rest of the triple, however, a computed architecture name may 765 // be needed. 766 llvm::Triple Triple(ToolChain::ComputeEffectiveClangTriple(Args, InputType)); 767 if (Triple.getEnvironment() == llvm::Triple::MSVC) { 768 StringRef ObjFmt = Triple.getEnvironmentName().split('-').second; 769 if (ObjFmt.empty()) 770 Triple.setEnvironmentName((Twine("msvc") + MSVT.getAsString()).str()); 771 else 772 Triple.setEnvironmentName( 773 (Twine("msvc") + MSVT.getAsString() + Twine('-') + ObjFmt).str()); 774 } 775 return Triple.getTriple(); 776 } 777 778 SanitizerMask MSVCToolChain::getSupportedSanitizers() const { 779 SanitizerMask Res = ToolChain::getSupportedSanitizers(); 780 Res |= SanitizerKind::Address; 781 Res |= SanitizerKind::PointerCompare; 782 Res |= SanitizerKind::PointerSubtract; 783 Res |= SanitizerKind::Fuzzer; 784 Res |= SanitizerKind::FuzzerNoLink; 785 Res &= ~SanitizerKind::CFIMFCall; 786 return Res; 787 } 788 789 static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL, 790 bool SupportsForcingFramePointer, 791 const char *ExpandChar, const OptTable &Opts) { 792 assert(A->getOption().matches(options::OPT__SLASH_O)); 793 794 StringRef OptStr = A->getValue(); 795 for (size_t I = 0, E = OptStr.size(); I != E; ++I) { 796 const char &OptChar = *(OptStr.data() + I); 797 switch (OptChar) { 798 default: 799 break; 800 case '1': 801 case '2': 802 case 'x': 803 case 'd': 804 // Ignore /O[12xd] flags that aren't the last one on the command line. 805 // Only the last one gets expanded. 806 if (&OptChar != ExpandChar) { 807 A->claim(); 808 break; 809 } 810 if (OptChar == 'd') { 811 DAL.AddFlagArg(A, Opts.getOption(options::OPT_O0)); 812 } else { 813 if (OptChar == '1') { 814 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s"); 815 } else if (OptChar == '2' || OptChar == 'x') { 816 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin)); 817 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2"); 818 } 819 if (SupportsForcingFramePointer && 820 !DAL.hasArgNoClaim(options::OPT_fno_omit_frame_pointer)) 821 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fomit_frame_pointer)); 822 if (OptChar == '1' || OptChar == '2') 823 DAL.AddFlagArg(A, Opts.getOption(options::OPT_ffunction_sections)); 824 } 825 break; 826 case 'b': 827 if (I + 1 != E && isdigit(OptStr[I + 1])) { 828 switch (OptStr[I + 1]) { 829 case '0': 830 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_inline)); 831 break; 832 case '1': 833 DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_hint_functions)); 834 break; 835 case '2': 836 DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_functions)); 837 break; 838 } 839 ++I; 840 } 841 break; 842 case 'g': 843 A->claim(); 844 break; 845 case 'i': 846 if (I + 1 != E && OptStr[I + 1] == '-') { 847 ++I; 848 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin)); 849 } else { 850 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin)); 851 } 852 break; 853 case 's': 854 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s"); 855 break; 856 case 't': 857 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2"); 858 break; 859 case 'y': { 860 bool OmitFramePointer = true; 861 if (I + 1 != E && OptStr[I + 1] == '-') { 862 OmitFramePointer = false; 863 ++I; 864 } 865 if (SupportsForcingFramePointer) { 866 if (OmitFramePointer) 867 DAL.AddFlagArg(A, 868 Opts.getOption(options::OPT_fomit_frame_pointer)); 869 else 870 DAL.AddFlagArg( 871 A, Opts.getOption(options::OPT_fno_omit_frame_pointer)); 872 } else { 873 // Don't warn about /Oy- in x86-64 builds (where 874 // SupportsForcingFramePointer is false). The flag having no effect 875 // there is a compiler-internal optimization, and people shouldn't have 876 // to special-case their build files for x86-64 clang-cl. 877 A->claim(); 878 } 879 break; 880 } 881 } 882 } 883 } 884 885 static void TranslateDArg(Arg *A, llvm::opt::DerivedArgList &DAL, 886 const OptTable &Opts) { 887 assert(A->getOption().matches(options::OPT_D)); 888 889 StringRef Val = A->getValue(); 890 size_t Hash = Val.find('#'); 891 if (Hash == StringRef::npos || Hash > Val.find('=')) { 892 DAL.append(A); 893 return; 894 } 895 896 std::string NewVal = std::string(Val); 897 NewVal[Hash] = '='; 898 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_D), NewVal); 899 } 900 901 static void TranslatePermissive(Arg *A, llvm::opt::DerivedArgList &DAL, 902 const OptTable &Opts) { 903 DAL.AddFlagArg(A, Opts.getOption(options::OPT__SLASH_Zc_twoPhase_)); 904 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_operator_names)); 905 } 906 907 static void TranslatePermissiveMinus(Arg *A, llvm::opt::DerivedArgList &DAL, 908 const OptTable &Opts) { 909 DAL.AddFlagArg(A, Opts.getOption(options::OPT__SLASH_Zc_twoPhase)); 910 DAL.AddFlagArg(A, Opts.getOption(options::OPT_foperator_names)); 911 } 912 913 llvm::opt::DerivedArgList * 914 MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args, 915 StringRef BoundArch, 916 Action::OffloadKind OFK) const { 917 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); 918 const OptTable &Opts = getDriver().getOpts(); 919 920 // /Oy and /Oy- don't have an effect on X86-64 921 bool SupportsForcingFramePointer = getArch() != llvm::Triple::x86_64; 922 923 // The -O[12xd] flag actually expands to several flags. We must desugar the 924 // flags so that options embedded can be negated. For example, the '-O2' flag 925 // enables '-Oy'. Expanding '-O2' into its constituent flags allows us to 926 // correctly handle '-O2 -Oy-' where the trailing '-Oy-' disables a single 927 // aspect of '-O2'. 928 // 929 // Note that this expansion logic only applies to the *last* of '[12xd]'. 930 931 // First step is to search for the character we'd like to expand. 932 const char *ExpandChar = nullptr; 933 for (Arg *A : Args.filtered(options::OPT__SLASH_O)) { 934 StringRef OptStr = A->getValue(); 935 for (size_t I = 0, E = OptStr.size(); I != E; ++I) { 936 char OptChar = OptStr[I]; 937 char PrevChar = I > 0 ? OptStr[I - 1] : '0'; 938 if (PrevChar == 'b') { 939 // OptChar does not expand; it's an argument to the previous char. 940 continue; 941 } 942 if (OptChar == '1' || OptChar == '2' || OptChar == 'x' || OptChar == 'd') 943 ExpandChar = OptStr.data() + I; 944 } 945 } 946 947 for (Arg *A : Args) { 948 if (A->getOption().matches(options::OPT__SLASH_O)) { 949 // The -O flag actually takes an amalgam of other options. For example, 950 // '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'. 951 TranslateOptArg(A, *DAL, SupportsForcingFramePointer, ExpandChar, Opts); 952 } else if (A->getOption().matches(options::OPT_D)) { 953 // Translate -Dfoo#bar into -Dfoo=bar. 954 TranslateDArg(A, *DAL, Opts); 955 } else if (A->getOption().matches(options::OPT__SLASH_permissive)) { 956 // Expand /permissive 957 TranslatePermissive(A, *DAL, Opts); 958 } else if (A->getOption().matches(options::OPT__SLASH_permissive_)) { 959 // Expand /permissive- 960 TranslatePermissiveMinus(A, *DAL, Opts); 961 } else if (OFK != Action::OFK_HIP) { 962 // HIP Toolchain translates input args by itself. 963 DAL->append(A); 964 } 965 } 966 967 return DAL; 968 } 969 970 void MSVCToolChain::addClangTargetOptions( 971 const ArgList &DriverArgs, ArgStringList &CC1Args, 972 Action::OffloadKind DeviceOffloadKind) const { 973 // MSVC STL kindly allows removing all usages of typeid by defining 974 // _HAS_STATIC_RTTI to 0. Do so, when compiling with -fno-rtti 975 if (DriverArgs.hasFlag(options::OPT_fno_rtti, options::OPT_frtti, 976 /*Default=*/false)) 977 CC1Args.push_back("-D_HAS_STATIC_RTTI=0"); 978 } 979