1 //===-- MSVC.cpp - MSVC ToolChain Implementations -------------------------===//
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
7 //===----------------------------------------------------------------------===//
10 #include "CommonArgs.h"
12 #include "clang/Basic/CharInfo.h"
13 #include "clang/Basic/Version.h"
14 #include "clang/Driver/Compilation.h"
15 #include "clang/Driver/Driver.h"
16 #include "clang/Driver/DriverDiagnostic.h"
17 #include "clang/Driver/Options.h"
18 #include "clang/Driver/SanitizerArgs.h"
19 #include "llvm/ADT/StringExtras.h"
20 #include "llvm/ADT/StringSwitch.h"
21 #include "llvm/Option/Arg.h"
22 #include "llvm/Option/ArgList.h"
23 #include "llvm/Support/ConvertUTF.h"
24 #include "llvm/Support/ErrorHandling.h"
25 #include "llvm/Support/FileSystem.h"
26 #include "llvm/Support/Host.h"
27 #include "llvm/Support/MemoryBuffer.h"
28 #include "llvm/Support/Path.h"
29 #include "llvm/Support/Process.h"
33 #define WIN32_LEAN_AND_MEAN
42 // Don't support SetupApi on MinGW.
43 #define USE_MSVC_SETUP_API
45 // Make sure this comes before MSVCSetupApi.h
48 #include "MSVCSetupApi.h"
49 #include "llvm/Support/COM.h"
50 _COM_SMARTPTR_TYPEDEF(ISetupConfiguration, __uuidof(ISetupConfiguration));
51 _COM_SMARTPTR_TYPEDEF(ISetupConfiguration2, __uuidof(ISetupConfiguration2));
52 _COM_SMARTPTR_TYPEDEF(ISetupHelper, __uuidof(ISetupHelper));
53 _COM_SMARTPTR_TYPEDEF(IEnumSetupInstances, __uuidof(IEnumSetupInstances));
54 _COM_SMARTPTR_TYPEDEF(ISetupInstance, __uuidof(ISetupInstance));
55 _COM_SMARTPTR_TYPEDEF(ISetupInstance2, __uuidof(ISetupInstance2));
58 using namespace clang::driver;
59 using namespace clang::driver::toolchains;
60 using namespace clang::driver::tools;
61 using namespace clang;
62 using namespace llvm::opt;
65 // Forward declare this so there aren't too many things above the constructor.
66 static bool getSystemRegistryString(const char *keyPath, const char *valueName,
67 std::string &value, std::string *phValue);
69 // Check various environment variables to try and find a toolchain.
70 static bool findVCToolChainViaEnvironment(std::string &Path,
71 MSVCToolChain::ToolsetLayout &VSLayout) {
72 // These variables are typically set by vcvarsall.bat
73 // when launching a developer command prompt.
74 if (llvm::Optional<std::string> VCToolsInstallDir =
75 llvm::sys::Process::GetEnv("VCToolsInstallDir")) {
76 // This is only set by newer Visual Studios, and it leads straight to
77 // the toolchain directory.
78 Path = std::move(*VCToolsInstallDir);
79 VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
82 if (llvm::Optional<std::string> VCInstallDir =
83 llvm::sys::Process::GetEnv("VCINSTALLDIR")) {
84 // If the previous variable isn't set but this one is, then we've found
85 // an older Visual Studio. This variable is set by newer Visual Studios too,
86 // so this check has to appear second.
87 // In older Visual Studios, the VC directory is the toolchain.
88 Path = std::move(*VCInstallDir);
89 VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
93 // We couldn't find any VC environment variables. Let's walk through PATH and
94 // see if it leads us to a VC toolchain bin directory. If it does, pick the
95 // first one that we find.
96 if (llvm::Optional<std::string> PathEnv =
97 llvm::sys::Process::GetEnv("PATH")) {
98 llvm::SmallVector<llvm::StringRef, 8> PathEntries;
99 llvm::StringRef(*PathEnv).split(PathEntries, llvm::sys::EnvPathSeparator);
100 for (llvm::StringRef PathEntry : PathEntries) {
101 if (PathEntry.empty())
104 llvm::SmallString<256> ExeTestPath;
106 // If cl.exe doesn't exist, then this definitely isn't a VC toolchain.
107 ExeTestPath = PathEntry;
108 llvm::sys::path::append(ExeTestPath, "cl.exe");
109 if (!llvm::sys::fs::exists(ExeTestPath))
112 // cl.exe existing isn't a conclusive test for a VC toolchain; clang also
113 // has a cl.exe. So let's check for link.exe too.
114 ExeTestPath = PathEntry;
115 llvm::sys::path::append(ExeTestPath, "link.exe");
116 if (!llvm::sys::fs::exists(ExeTestPath))
119 // whatever/VC/bin --> old toolchain, VC dir is toolchain dir.
120 llvm::StringRef TestPath = PathEntry;
121 bool IsBin = llvm::sys::path::filename(TestPath).equals_lower("bin");
123 // Strip any architecture subdir like "amd64".
124 TestPath = llvm::sys::path::parent_path(TestPath);
125 IsBin = llvm::sys::path::filename(TestPath).equals_lower("bin");
128 llvm::StringRef ParentPath = llvm::sys::path::parent_path(TestPath);
129 llvm::StringRef ParentFilename = llvm::sys::path::filename(ParentPath);
130 if (ParentFilename == "VC") {
132 VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
135 if (ParentFilename == "x86ret" || ParentFilename == "x86chk"
136 || ParentFilename == "amd64ret" || ParentFilename == "amd64chk") {
138 VSLayout = MSVCToolChain::ToolsetLayout::DevDivInternal;
143 // This could be a new (>=VS2017) toolchain. If it is, we should find
144 // path components with these prefixes when walking backwards through
146 // Note: empty strings match anything.
147 llvm::StringRef ExpectedPrefixes[] = {"", "Host", "bin", "",
148 "MSVC", "Tools", "VC"};
150 auto It = llvm::sys::path::rbegin(PathEntry);
151 auto End = llvm::sys::path::rend(PathEntry);
152 for (llvm::StringRef Prefix : ExpectedPrefixes) {
155 if (!It->startswith(Prefix))
160 // We've found a new toolchain!
161 // Back up 3 times (/bin/Host/arch) to get the root path.
162 llvm::StringRef ToolChainPath(PathEntry);
163 for (int i = 0; i < 3; ++i)
164 ToolChainPath = llvm::sys::path::parent_path(ToolChainPath);
166 Path = ToolChainPath;
167 VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
178 // Query the Setup Config server for installs, then pick the newest version
179 // and find its default VC toolchain.
180 // This is the preferred way to discover new Visual Studios, as they're no
181 // longer listed in the registry.
182 static bool findVCToolChainViaSetupConfig(std::string &Path,
183 MSVCToolChain::ToolsetLayout &VSLayout) {
184 #if !defined(USE_MSVC_SETUP_API)
187 // FIXME: This really should be done once in the top-level program's main
188 // function, as it may have already been initialized with a different
189 // threading model otherwise.
190 llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::SingleThreaded);
193 // _com_ptr_t will throw a _com_error if a COM calls fail.
194 // The LLVM coding standards forbid exception handling, so we'll have to
195 // stop them from being thrown in the first place.
196 // The destructor will put the regular error handler back when we leave
198 struct SuppressCOMErrorsRAII {
199 static void __stdcall handler(HRESULT hr, IErrorInfo *perrinfo) {}
201 SuppressCOMErrorsRAII() { _set_com_error_handler(handler); }
203 ~SuppressCOMErrorsRAII() { _set_com_error_handler(_com_raise_error); }
205 } COMErrorSuppressor;
207 ISetupConfigurationPtr Query;
208 HR = Query.CreateInstance(__uuidof(SetupConfiguration));
212 IEnumSetupInstancesPtr EnumInstances;
213 HR = ISetupConfiguration2Ptr(Query)->EnumAllInstances(&EnumInstances);
217 ISetupInstancePtr Instance;
218 HR = EnumInstances->Next(1, &Instance, nullptr);
222 ISetupInstancePtr NewestInstance;
223 Optional<uint64_t> NewestVersionNum;
225 bstr_t VersionString;
227 HR = Instance->GetInstallationVersion(VersionString.GetAddress());
230 HR = ISetupHelperPtr(Query)->ParseVersion(VersionString, &VersionNum);
233 if (!NewestVersionNum || (VersionNum > NewestVersionNum)) {
234 NewestInstance = Instance;
235 NewestVersionNum = VersionNum;
237 } while ((HR = EnumInstances->Next(1, &Instance, nullptr)) == S_OK);
243 HR = NewestInstance->ResolvePath(L"VC", VCPathWide.GetAddress());
247 std::string VCRootPath;
248 llvm::convertWideToUTF8(std::wstring(VCPathWide), VCRootPath);
250 llvm::SmallString<256> ToolsVersionFilePath(VCRootPath);
251 llvm::sys::path::append(ToolsVersionFilePath, "Auxiliary", "Build",
252 "Microsoft.VCToolsVersion.default.txt");
254 auto ToolsVersionFile = llvm::MemoryBuffer::getFile(ToolsVersionFilePath);
255 if (!ToolsVersionFile)
258 llvm::SmallString<256> ToolchainPath(VCRootPath);
259 llvm::sys::path::append(ToolchainPath, "Tools", "MSVC",
260 ToolsVersionFile->get()->getBuffer().rtrim());
261 if (!llvm::sys::fs::is_directory(ToolchainPath))
264 Path = ToolchainPath.str();
265 VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
270 // Look in the registry for Visual Studio installs, and use that to get
271 // a toolchain path. VS2017 and newer don't get added to the registry.
272 // So if we find something here, we know that it's an older version.
273 static bool findVCToolChainViaRegistry(std::string &Path,
274 MSVCToolChain::ToolsetLayout &VSLayout) {
275 std::string VSInstallPath;
276 if (getSystemRegistryString(R"(SOFTWARE\Microsoft\VisualStudio\$VERSION)",
277 "InstallDir", VSInstallPath, nullptr) ||
278 getSystemRegistryString(R"(SOFTWARE\Microsoft\VCExpress\$VERSION)",
279 "InstallDir", VSInstallPath, nullptr)) {
280 if (!VSInstallPath.empty()) {
281 llvm::SmallString<256> VCPath(llvm::StringRef(
282 VSInstallPath.c_str(), VSInstallPath.find(R"(\Common7\IDE)")));
283 llvm::sys::path::append(VCPath, "VC");
286 VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
293 // Try to find Exe from a Visual Studio distribution. This first tries to find
294 // an installed copy of Visual Studio and, failing that, looks in the PATH,
295 // making sure that whatever executable that's found is not a same-named exe
296 // from clang itself to prevent clang from falling back to itself.
297 static std::string FindVisualStudioExecutable(const ToolChain &TC,
299 const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC);
300 SmallString<128> FilePath(MSVC.getSubDirectoryPath(
301 toolchains::MSVCToolChain::SubDirectoryType::Bin));
302 llvm::sys::path::append(FilePath, Exe);
303 return llvm::sys::fs::can_execute(FilePath) ? FilePath.str() : Exe;
306 void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
307 const InputInfo &Output,
308 const InputInfoList &Inputs,
310 const char *LinkingOutput) const {
311 ArgStringList CmdArgs;
313 auto &TC = static_cast<const toolchains::MSVCToolChain &>(getToolChain());
315 assert((Output.isFilename() || Output.isNothing()) && "invalid output");
316 if (Output.isFilename())
318 Args.MakeArgString(std::string("-out:") + Output.getFilename()));
320 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) &&
321 !C.getDriver().IsCLMode())
322 CmdArgs.push_back("-defaultlib:libcmt");
324 if (!llvm::sys::Process::GetEnv("LIB")) {
325 // If the VC environment hasn't been configured (perhaps because the user
326 // did not run vcvarsall), try to build a consistent link environment. If
327 // the environment variable is set however, assume the user knows what
329 CmdArgs.push_back(Args.MakeArgString(
331 TC.getSubDirectoryPath(
332 toolchains::MSVCToolChain::SubDirectoryType::Lib)));
334 if (TC.useUniversalCRT()) {
335 std::string UniversalCRTLibPath;
336 if (TC.getUniversalCRTLibraryPath(UniversalCRTLibPath))
338 Args.MakeArgString(Twine("-libpath:") + UniversalCRTLibPath));
341 std::string WindowsSdkLibPath;
342 if (TC.getWindowsSDKLibraryPath(WindowsSdkLibPath))
344 Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath));
347 if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L))
348 for (const auto &LibPath : Args.getAllArgValues(options::OPT_L))
349 CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath));
351 CmdArgs.push_back("-nologo");
353 if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7,
354 options::OPT__SLASH_Zd))
355 CmdArgs.push_back("-debug");
357 // Pass on /Brepro if it was passed to the compiler.
358 // Note that /Brepro maps to -mno-incremental-linker-compatible.
359 bool DefaultIncrementalLinkerCompatible =
360 C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment();
361 if (!Args.hasFlag(options::OPT_mincremental_linker_compatible,
362 options::OPT_mno_incremental_linker_compatible,
363 DefaultIncrementalLinkerCompatible))
364 CmdArgs.push_back("-Brepro");
366 bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd,
367 options::OPT_shared);
369 CmdArgs.push_back(Args.MakeArgString("-dll"));
371 SmallString<128> ImplibName(Output.getFilename());
372 llvm::sys::path::replace_extension(ImplibName, "lib");
373 CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName));
376 if (TC.getSanitizerArgs().needsFuzzer()) {
377 if (!Args.hasArg(options::OPT_shared))
379 Args.MakeArgString(std::string("-wholearchive:") +
380 TC.getCompilerRTArgString(Args, "fuzzer")));
381 CmdArgs.push_back(Args.MakeArgString("-debug"));
382 // Prevent the linker from padding sections we use for instrumentation
384 CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
387 if (TC.getSanitizerArgs().needsAsanRt()) {
388 CmdArgs.push_back(Args.MakeArgString("-debug"));
389 CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
390 if (TC.getSanitizerArgs().needsSharedRt() ||
391 Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
392 for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
393 CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
394 // Make sure the dynamic runtime thunk is not optimized out at link time
395 // to ensure proper SEH handling.
396 CmdArgs.push_back(Args.MakeArgString(
397 TC.getArch() == llvm::Triple::x86
398 ? "-include:___asan_seh_interceptor"
399 : "-include:__asan_seh_interceptor"));
400 // Make sure the linker consider all object files from the dynamic runtime
402 CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
403 TC.getCompilerRT(Args, "asan_dynamic_runtime_thunk")));
405 CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
407 for (const auto &Lib : {"asan", "asan_cxx"}) {
408 CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
409 // Make sure the linker consider all object files from the static lib.
410 // This is necessary because instrumented dlls need access to all the
411 // interface exported by the static lib in the main executable.
412 CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
413 TC.getCompilerRT(Args, Lib)));
418 Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link);
420 if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
421 options::OPT_fno_openmp, false)) {
422 CmdArgs.push_back("-nodefaultlib:vcomp.lib");
423 CmdArgs.push_back("-nodefaultlib:vcompd.lib");
424 CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
425 TC.getDriver().Dir + "/../lib"));
426 switch (TC.getDriver().getOpenMPRuntime(Args)) {
427 case Driver::OMPRT_OMP:
428 CmdArgs.push_back("-defaultlib:libomp.lib");
430 case Driver::OMPRT_IOMP5:
431 CmdArgs.push_back("-defaultlib:libiomp5md.lib");
433 case Driver::OMPRT_GOMP:
435 case Driver::OMPRT_Unknown:
436 // Already diagnosed.
441 // Add compiler-rt lib in case if it was explicitly
442 // specified as an argument for --rtlib option.
443 if (!Args.hasArg(options::OPT_nostdlib)) {
444 AddRunTimeLibs(TC, TC.getDriver(), CmdArgs, Args);
447 // Add filenames, libraries, and other linker inputs.
448 for (const auto &Input : Inputs) {
449 if (Input.isFilename()) {
450 CmdArgs.push_back(Input.getFilename());
454 const Arg &A = Input.getInputArg();
456 // Render -l options differently for the MSVC linker.
457 if (A.getOption().matches(options::OPT_l)) {
458 StringRef Lib = A.getValue();
459 const char *LinkLibArg;
460 if (Lib.endswith(".lib"))
461 LinkLibArg = Args.MakeArgString(Lib);
463 LinkLibArg = Args.MakeArgString(Lib + ".lib");
464 CmdArgs.push_back(LinkLibArg);
468 // Otherwise, this is some other kind of linker input option like -Wl, -z,
469 // or -L. Render it, even if MSVC doesn't understand it.
470 A.renderAsInput(Args, CmdArgs);
473 TC.addProfileRTLibs(Args, CmdArgs);
475 std::vector<const char *> Environment;
477 // We need to special case some linker paths. In the case of lld, we need to
478 // translate 'lld' into 'lld-link', and in the case of the regular msvc
479 // linker, we need to use a special search algorithm.
480 llvm::SmallString<128> linkPath;
481 StringRef Linker = Args.getLastArgValue(options::OPT_fuse_ld_EQ, "link");
482 if (Linker.equals_lower("lld"))
485 if (Linker.equals_lower("link")) {
486 // If we're using the MSVC linker, it's not sufficient to just use link
487 // from the program PATH, because other environments like GnuWin32 install
488 // their own link.exe which may come first.
489 linkPath = FindVisualStudioExecutable(TC, "link.exe");
491 if (!TC.FoundMSVCInstall() && !llvm::sys::fs::can_execute(linkPath)) {
492 llvm::SmallString<128> ClPath;
493 ClPath = TC.GetProgramPath("cl.exe");
494 if (llvm::sys::fs::can_execute(ClPath)) {
495 linkPath = llvm::sys::path::parent_path(ClPath);
496 llvm::sys::path::append(linkPath, "link.exe");
497 if (!llvm::sys::fs::can_execute(linkPath))
498 C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
500 C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
505 // When cross-compiling with VS2017 or newer, link.exe expects to have
506 // its containing bin directory at the top of PATH, followed by the
507 // native target bin directory.
508 // e.g. when compiling for x86 on an x64 host, PATH should start with:
509 // /bin/Hostx64/x86;/bin/Hostx64/x64
510 // This doesn't attempt to handle ToolsetLayout::DevDivInternal.
511 if (TC.getIsVS2017OrNewer() &&
512 llvm::Triple(llvm::sys::getProcessTriple()).getArch() != TC.getArch()) {
513 auto HostArch = llvm::Triple(llvm::sys::getProcessTriple()).getArch();
516 std::unique_ptr<wchar_t[], decltype(&FreeEnvironmentStringsW)>(
517 GetEnvironmentStringsW(), FreeEnvironmentStringsW);
519 goto SkipSettingEnvironment;
522 size_t EnvBlockLen = 0;
523 while (EnvBlockWide[EnvBlockLen] != L'\0') {
525 EnvBlockLen += std::wcslen(&EnvBlockWide[EnvBlockLen]) +
526 1 /*string null-terminator*/;
528 ++EnvBlockLen; // add the block null-terminator
530 std::string EnvBlock;
531 if (!llvm::convertUTF16ToUTF8String(
532 llvm::ArrayRef<char>(reinterpret_cast<char *>(EnvBlockWide.get()),
533 EnvBlockLen * sizeof(EnvBlockWide[0])),
535 goto SkipSettingEnvironment;
537 Environment.reserve(EnvCount);
539 // Now loop over each string in the block and copy them into the
540 // environment vector, adjusting the PATH variable as needed when we
542 for (const char *Cursor = EnvBlock.data(); *Cursor != '\0';) {
543 llvm::StringRef EnvVar(Cursor);
544 if (EnvVar.startswith_lower("path=")) {
545 using SubDirectoryType = toolchains::MSVCToolChain::SubDirectoryType;
546 constexpr size_t PrefixLen = 5; // strlen("path=")
547 Environment.push_back(Args.MakeArgString(
548 EnvVar.substr(0, PrefixLen) +
549 TC.getSubDirectoryPath(SubDirectoryType::Bin) +
550 llvm::Twine(llvm::sys::EnvPathSeparator) +
551 TC.getSubDirectoryPath(SubDirectoryType::Bin, HostArch) +
552 (EnvVar.size() > PrefixLen
553 ? llvm::Twine(llvm::sys::EnvPathSeparator) +
554 EnvVar.substr(PrefixLen)
557 Environment.push_back(Args.MakeArgString(EnvVar));
559 Cursor += EnvVar.size() + 1 /*null-terminator*/;
562 SkipSettingEnvironment:;
565 linkPath = TC.GetProgramPath(Linker.str().c_str());
568 auto LinkCmd = llvm::make_unique<Command>(
569 JA, *this, Args.MakeArgString(linkPath), CmdArgs, Inputs);
570 if (!Environment.empty())
571 LinkCmd->setEnvironment(Environment);
572 C.addCommand(std::move(LinkCmd));
575 void visualstudio::Compiler::ConstructJob(Compilation &C, const JobAction &JA,
576 const InputInfo &Output,
577 const InputInfoList &Inputs,
579 const char *LinkingOutput) const {
580 C.addCommand(GetCommand(C, JA, Output, Inputs, Args, LinkingOutput));
583 std::unique_ptr<Command> visualstudio::Compiler::GetCommand(
584 Compilation &C, const JobAction &JA, const InputInfo &Output,
585 const InputInfoList &Inputs, const ArgList &Args,
586 const char *LinkingOutput) const {
587 ArgStringList CmdArgs;
588 CmdArgs.push_back("/nologo");
589 CmdArgs.push_back("/c"); // Compile only.
590 CmdArgs.push_back("/W0"); // No warnings.
592 // The goal is to be able to invoke this tool correctly based on
593 // any flag accepted by clang-cl.
595 // These are spelled the same way in clang and cl.exe,.
596 Args.AddAllArgs(CmdArgs, {options::OPT_D, options::OPT_U, options::OPT_I});
598 // Optimization level.
599 if (Arg *A = Args.getLastArg(options::OPT_fbuiltin, options::OPT_fno_builtin))
600 CmdArgs.push_back(A->getOption().getID() == options::OPT_fbuiltin ? "/Oi"
602 if (Arg *A = Args.getLastArg(options::OPT_O, options::OPT_O0)) {
603 if (A->getOption().getID() == options::OPT_O0) {
604 CmdArgs.push_back("/Od");
606 CmdArgs.push_back("/Og");
608 StringRef OptLevel = A->getValue();
609 if (OptLevel == "s" || OptLevel == "z")
610 CmdArgs.push_back("/Os");
612 CmdArgs.push_back("/Ot");
614 CmdArgs.push_back("/Ob2");
617 if (Arg *A = Args.getLastArg(options::OPT_fomit_frame_pointer,
618 options::OPT_fno_omit_frame_pointer))
619 CmdArgs.push_back(A->getOption().getID() == options::OPT_fomit_frame_pointer
622 if (!Args.hasArg(options::OPT_fwritable_strings))
623 CmdArgs.push_back("/GF");
625 // Flags for which clang-cl has an alias.
626 // FIXME: How can we ensure this stays in sync with relevant clang-cl options?
628 if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR,
630 CmdArgs.push_back("/GR-");
632 if (Args.hasFlag(options::OPT__SLASH_GS_, options::OPT__SLASH_GS,
634 CmdArgs.push_back("/GS-");
636 if (Arg *A = Args.getLastArg(options::OPT_ffunction_sections,
637 options::OPT_fno_function_sections))
638 CmdArgs.push_back(A->getOption().getID() == options::OPT_ffunction_sections
641 if (Arg *A = Args.getLastArg(options::OPT_fdata_sections,
642 options::OPT_fno_data_sections))
644 A->getOption().getID() == options::OPT_fdata_sections ? "/Gw" : "/Gw-");
645 if (Args.hasArg(options::OPT_fsyntax_only))
646 CmdArgs.push_back("/Zs");
647 if (Args.hasArg(options::OPT_g_Flag, options::OPT_gline_tables_only,
648 options::OPT__SLASH_Z7))
649 CmdArgs.push_back("/Z7");
651 std::vector<std::string> Includes =
652 Args.getAllArgValues(options::OPT_include);
653 for (const auto &Include : Includes)
654 CmdArgs.push_back(Args.MakeArgString(std::string("/FI") + Include));
656 // Flags that can simply be passed through.
657 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LD);
658 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LDd);
659 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_GX);
660 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_GX_);
661 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_EH);
662 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_Zl);
664 // The order of these flags is relevant, so pick the last one.
665 if (Arg *A = Args.getLastArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd,
666 options::OPT__SLASH_MT, options::OPT__SLASH_MTd))
667 A->render(Args, CmdArgs);
669 // Use MSVC's default threadsafe statics behaviour unless there was a flag.
670 if (Arg *A = Args.getLastArg(options::OPT_fthreadsafe_statics,
671 options::OPT_fno_threadsafe_statics)) {
672 CmdArgs.push_back(A->getOption().getID() == options::OPT_fthreadsafe_statics
673 ? "/Zc:threadSafeInit"
674 : "/Zc:threadSafeInit-");
677 // Pass through all unknown arguments so that the fallback command can see
679 Args.AddAllArgs(CmdArgs, options::OPT_UNKNOWN);
682 assert(Inputs.size() == 1);
683 const InputInfo &II = Inputs[0];
684 assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX);
685 CmdArgs.push_back(II.getType() == types::TY_C ? "/Tc" : "/Tp");
687 CmdArgs.push_back(II.getFilename());
689 II.getInputArg().renderAsInput(Args, CmdArgs);
692 assert(Output.getType() == types::TY_Object);
694 Args.MakeArgString(std::string("/Fo") + Output.getFilename());
695 CmdArgs.push_back(Fo);
697 std::string Exec = FindVisualStudioExecutable(getToolChain(), "cl.exe");
698 return llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
702 MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
704 : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args) {
705 getProgramPaths().push_back(getDriver().getInstalledDir());
706 if (getDriver().getInstalledDir() != getDriver().Dir)
707 getProgramPaths().push_back(getDriver().Dir);
709 // Check the environment first, since that's probably the user telling us
710 // what they want to use.
711 // Failing that, just try to find the newest Visual Studio version we can
712 // and use its default VC toolchain.
713 findVCToolChainViaEnvironment(VCToolChainPath, VSLayout) ||
714 findVCToolChainViaSetupConfig(VCToolChainPath, VSLayout) ||
715 findVCToolChainViaRegistry(VCToolChainPath, VSLayout);
718 Tool *MSVCToolChain::buildLinker() const {
719 return new tools::visualstudio::Linker(*this);
722 Tool *MSVCToolChain::buildAssembler() const {
723 if (getTriple().isOSBinFormatMachO())
724 return new tools::darwin::Assembler(*this);
725 getDriver().Diag(clang::diag::err_no_external_assembler);
729 bool MSVCToolChain::IsIntegratedAssemblerDefault() const {
733 bool MSVCToolChain::IsUnwindTablesDefault(const ArgList &Args) const {
734 // Don't emit unwind tables by default for MachO targets.
735 if (getTriple().isOSBinFormatMachO())
738 // All non-x86_32 Windows targets require unwind tables. However, LLVM
739 // doesn't know how to generate them for all targets, so only enable
740 // the ones that are actually implemented.
741 return getArch() == llvm::Triple::x86_64 ||
742 getArch() == llvm::Triple::aarch64;
745 bool MSVCToolChain::isPICDefault() const {
746 return getArch() == llvm::Triple::x86_64;
749 bool MSVCToolChain::isPIEDefault() const {
753 bool MSVCToolChain::isPICDefaultForced() const {
754 return getArch() == llvm::Triple::x86_64;
757 void MSVCToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
758 ArgStringList &CC1Args) const {
759 CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
762 void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const {
763 CudaInstallation.print(OS);
766 // Windows SDKs and VC Toolchains group their contents into subdirectories based
767 // on the target architecture. This function converts an llvm::Triple::ArchType
768 // to the corresponding subdirectory name.
769 static const char *llvmArchToWindowsSDKArch(llvm::Triple::ArchType Arch) {
770 using ArchType = llvm::Triple::ArchType;
774 case ArchType::x86_64:
778 case ArchType::aarch64:
785 // Similar to the above function, but for Visual Studios before VS2017.
786 static const char *llvmArchToLegacyVCArch(llvm::Triple::ArchType Arch) {
787 using ArchType = llvm::Triple::ArchType;
790 // x86 is default in legacy VC toolchains.
791 // e.g. x86 libs are directly in /lib as opposed to /lib/x86.
793 case ArchType::x86_64:
797 case ArchType::aarch64:
804 // Similar to the above function, but for DevDiv internal builds.
805 static const char *llvmArchToDevDivInternalArch(llvm::Triple::ArchType Arch) {
806 using ArchType = llvm::Triple::ArchType;
810 case ArchType::x86_64:
814 case ArchType::aarch64:
821 // Get the path to a specific subdirectory in the current toolchain for
822 // a given target architecture.
823 // VS2017 changed the VC toolchain layout, so this should be used instead
824 // of hardcoding paths.
826 MSVCToolChain::getSubDirectoryPath(SubDirectoryType Type,
827 llvm::Triple::ArchType TargetArch) const {
828 const char *SubdirName;
829 const char *IncludeName;
831 case ToolsetLayout::OlderVS:
832 SubdirName = llvmArchToLegacyVCArch(TargetArch);
833 IncludeName = "include";
835 case ToolsetLayout::VS2017OrNewer:
836 SubdirName = llvmArchToWindowsSDKArch(TargetArch);
837 IncludeName = "include";
839 case ToolsetLayout::DevDivInternal:
840 SubdirName = llvmArchToDevDivInternalArch(TargetArch);
845 llvm::SmallString<256> Path(VCToolChainPath);
847 case SubDirectoryType::Bin:
848 if (VSLayout == ToolsetLayout::VS2017OrNewer) {
849 const bool HostIsX64 =
850 llvm::Triple(llvm::sys::getProcessTriple()).isArch64Bit();
851 const char *const HostName = HostIsX64 ? "Hostx64" : "Hostx86";
852 llvm::sys::path::append(Path, "bin", HostName, SubdirName);
853 } else { // OlderVS or DevDivInternal
854 llvm::sys::path::append(Path, "bin", SubdirName);
857 case SubDirectoryType::Include:
858 llvm::sys::path::append(Path, IncludeName);
860 case SubDirectoryType::Lib:
861 llvm::sys::path::append(Path, "lib", SubdirName);
868 static bool readFullStringValue(HKEY hkey, const char *valueName,
869 std::string &value) {
870 std::wstring WideValueName;
871 if (!llvm::ConvertUTF8toWide(valueName, WideValueName))
877 // First just query for the required size.
878 result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, &type, NULL,
880 if (result != ERROR_SUCCESS || type != REG_SZ || !valueSize)
882 std::vector<BYTE> buffer(valueSize);
883 result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, NULL, &buffer[0],
885 if (result == ERROR_SUCCESS) {
886 std::wstring WideValue(reinterpret_cast<const wchar_t *>(buffer.data()),
887 valueSize / sizeof(wchar_t));
888 if (valueSize && WideValue.back() == L'\0') {
889 WideValue.pop_back();
891 // The destination buffer must be empty as an invariant of the conversion
892 // function; but this function is sometimes called in a loop that passes in
893 // the same buffer, however. Simply clear it out so we can overwrite it.
895 return llvm::convertWideToUTF8(WideValue, value);
901 /// Read registry string.
902 /// This also supports a means to look for high-versioned keys by use
903 /// of a $VERSION placeholder in the key path.
904 /// $VERSION in the key path is a placeholder for the version number,
905 /// causing the highest value path to be searched for and used.
906 /// I.e. "SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
907 /// There can be additional characters in the component. Only the numeric
908 /// characters are compared. This function only searches HKLM.
909 static bool getSystemRegistryString(const char *keyPath, const char *valueName,
910 std::string &value, std::string *phValue) {
914 HKEY hRootKey = HKEY_LOCAL_MACHINE;
917 bool returnValue = false;
919 const char *placeHolder = strstr(keyPath, "$VERSION");
920 std::string bestName;
921 // If we have a $VERSION placeholder, do the highest-version search.
923 const char *keyEnd = placeHolder - 1;
924 const char *nextKey = placeHolder;
925 // Find end of previous key.
926 while ((keyEnd > keyPath) && (*keyEnd != '\\'))
928 // Find end of key containing $VERSION.
929 while (*nextKey && (*nextKey != '\\'))
931 size_t partialKeyLength = keyEnd - keyPath;
932 char partialKey[256];
933 if (partialKeyLength >= sizeof(partialKey))
934 partialKeyLength = sizeof(partialKey) - 1;
935 strncpy(partialKey, keyPath, partialKeyLength);
936 partialKey[partialKeyLength] = '\0';
938 lResult = RegOpenKeyExA(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY,
940 if (lResult == ERROR_SUCCESS) {
942 double bestValue = 0.0;
943 DWORD index, size = sizeof(keyName) - 1;
944 for (index = 0; RegEnumKeyExA(hTopKey, index, keyName, &size, NULL, NULL,
945 NULL, NULL) == ERROR_SUCCESS;
947 const char *sp = keyName;
948 while (*sp && !isDigit(*sp))
952 const char *ep = sp + 1;
953 while (*ep && (isDigit(*ep) || (*ep == '.')))
956 strncpy(numBuf, sp, sizeof(numBuf) - 1);
957 numBuf[sizeof(numBuf) - 1] = '\0';
958 double dvalue = strtod(numBuf, NULL);
959 if (dvalue > bestValue) {
960 // Test that InstallDir is indeed there before keeping this index.
961 // Open the chosen key path remainder.
963 // Append rest of key.
964 bestName.append(nextKey);
965 lResult = RegOpenKeyExA(hTopKey, bestName.c_str(), 0,
966 KEY_READ | KEY_WOW64_32KEY, &hKey);
967 if (lResult == ERROR_SUCCESS) {
968 if (readFullStringValue(hKey, valueName, value)) {
977 size = sizeof(keyName) - 1;
979 RegCloseKey(hTopKey);
983 RegOpenKeyExA(hRootKey, keyPath, 0, KEY_READ | KEY_WOW64_32KEY, &hKey);
984 if (lResult == ERROR_SUCCESS) {
985 if (readFullStringValue(hKey, valueName, value))
996 // Find the most recent version of Universal CRT or Windows 10 SDK.
997 // vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include
998 // directory by name and uses the last one of the list.
999 // So we compare entry names lexicographically to find the greatest one.
1000 static bool getWindows10SDKVersionFromPath(const std::string &SDKPath,
1001 std::string &SDKVersion) {
1005 llvm::SmallString<128> IncludePath(SDKPath);
1006 llvm::sys::path::append(IncludePath, "Include");
1007 for (llvm::sys::fs::directory_iterator DirIt(IncludePath, EC), DirEnd;
1008 DirIt != DirEnd && !EC; DirIt.increment(EC)) {
1009 if (!llvm::sys::fs::is_directory(DirIt->path()))
1011 StringRef CandidateName = llvm::sys::path::filename(DirIt->path());
1012 // If WDK is installed, there could be subfolders like "wdf" in the
1013 // "Include" directory.
1014 // Allow only directories which names start with "10.".
1015 if (!CandidateName.startswith("10."))
1017 if (CandidateName > SDKVersion)
1018 SDKVersion = CandidateName;
1021 return !SDKVersion.empty();
1024 /// Get Windows SDK installation directory.
1025 static bool getWindowsSDKDir(std::string &Path, int &Major,
1026 std::string &WindowsSDKIncludeVersion,
1027 std::string &WindowsSDKLibVersion) {
1028 std::string RegistrySDKVersion;
1029 // Try the Windows registry.
1030 if (!getSystemRegistryString(
1031 "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
1032 "InstallationFolder", Path, &RegistrySDKVersion))
1034 if (Path.empty() || RegistrySDKVersion.empty())
1037 WindowsSDKIncludeVersion.clear();
1038 WindowsSDKLibVersion.clear();
1040 std::sscanf(RegistrySDKVersion.c_str(), "v%d.", &Major);
1044 // Windows SDK 8.x installs libraries in a folder whose names depend on the
1045 // version of the OS you're targeting. By default choose the newest, which
1046 // usually corresponds to the version of the OS you've installed the SDK on.
1047 const char *Tests[] = {"winv6.3", "win8", "win7"};
1048 for (const char *Test : Tests) {
1049 llvm::SmallString<128> TestPath(Path);
1050 llvm::sys::path::append(TestPath, "Lib", Test);
1051 if (llvm::sys::fs::exists(TestPath.c_str())) {
1052 WindowsSDKLibVersion = Test;
1056 return !WindowsSDKLibVersion.empty();
1059 if (!getWindows10SDKVersionFromPath(Path, WindowsSDKIncludeVersion))
1061 WindowsSDKLibVersion = WindowsSDKIncludeVersion;
1064 // Unsupported SDK version
1068 // Gets the library path required to link against the Windows SDK.
1069 bool MSVCToolChain::getWindowsSDKLibraryPath(std::string &path) const {
1070 std::string sdkPath;
1072 std::string windowsSDKIncludeVersion;
1073 std::string windowsSDKLibVersion;
1076 if (!getWindowsSDKDir(sdkPath, sdkMajor, windowsSDKIncludeVersion,
1077 windowsSDKLibVersion))
1080 llvm::SmallString<128> libPath(sdkPath);
1081 llvm::sys::path::append(libPath, "Lib");
1082 if (sdkMajor >= 8) {
1083 llvm::sys::path::append(libPath, windowsSDKLibVersion, "um",
1084 llvmArchToWindowsSDKArch(getArch()));
1086 switch (getArch()) {
1087 // In Windows SDK 7.x, x86 libraries are directly in the Lib folder.
1088 case llvm::Triple::x86:
1090 case llvm::Triple::x86_64:
1091 llvm::sys::path::append(libPath, "x64");
1093 case llvm::Triple::arm:
1094 // It is not necessary to link against Windows SDK 7.x when targeting ARM.
1101 path = libPath.str();
1105 // Check if the Include path of a specified version of Visual Studio contains
1106 // specific header files. If not, they are probably shipped with Universal CRT.
1107 bool MSVCToolChain::useUniversalCRT() const {
1108 llvm::SmallString<128> TestPath(
1109 getSubDirectoryPath(SubDirectoryType::Include));
1110 llvm::sys::path::append(TestPath, "stdlib.h");
1111 return !llvm::sys::fs::exists(TestPath);
1114 static bool getUniversalCRTSdkDir(std::string &Path, std::string &UCRTVersion) {
1115 // vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry
1116 // for the specific key "KitsRoot10". So do we.
1117 if (!getSystemRegistryString(
1118 "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10",
1122 return getWindows10SDKVersionFromPath(Path, UCRTVersion);
1125 bool MSVCToolChain::getUniversalCRTLibraryPath(std::string &Path) const {
1126 std::string UniversalCRTSdkPath;
1127 std::string UCRTVersion;
1130 if (!getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion))
1133 StringRef ArchName = llvmArchToWindowsSDKArch(getArch());
1134 if (ArchName.empty())
1137 llvm::SmallString<128> LibPath(UniversalCRTSdkPath);
1138 llvm::sys::path::append(LibPath, "Lib", UCRTVersion, "ucrt", ArchName);
1140 Path = LibPath.str();
1144 static VersionTuple getMSVCVersionFromTriple(const llvm::Triple &Triple) {
1145 unsigned Major, Minor, Micro;
1146 Triple.getEnvironmentVersion(Major, Minor, Micro);
1147 if (Major || Minor || Micro)
1148 return VersionTuple(Major, Minor, Micro);
1149 return VersionTuple();
1152 static VersionTuple getMSVCVersionFromExe(const std::string &BinDir) {
1153 VersionTuple Version;
1155 SmallString<128> ClExe(BinDir);
1156 llvm::sys::path::append(ClExe, "cl.exe");
1158 std::wstring ClExeWide;
1159 if (!llvm::ConvertUTF8toWide(ClExe.c_str(), ClExeWide))
1162 const DWORD VersionSize = ::GetFileVersionInfoSizeW(ClExeWide.c_str(),
1164 if (VersionSize == 0)
1167 SmallVector<uint8_t, 4 * 1024> VersionBlock(VersionSize);
1168 if (!::GetFileVersionInfoW(ClExeWide.c_str(), 0, VersionSize,
1169 VersionBlock.data()))
1172 VS_FIXEDFILEINFO *FileInfo = nullptr;
1173 UINT FileInfoSize = 0;
1174 if (!::VerQueryValueW(VersionBlock.data(), L"\\",
1175 reinterpret_cast<LPVOID *>(&FileInfo), &FileInfoSize) ||
1176 FileInfoSize < sizeof(*FileInfo))
1179 const unsigned Major = (FileInfo->dwFileVersionMS >> 16) & 0xFFFF;
1180 const unsigned Minor = (FileInfo->dwFileVersionMS ) & 0xFFFF;
1181 const unsigned Micro = (FileInfo->dwFileVersionLS >> 16) & 0xFFFF;
1183 Version = VersionTuple(Major, Minor, Micro);
1188 void MSVCToolChain::AddSystemIncludeWithSubfolder(
1189 const ArgList &DriverArgs, ArgStringList &CC1Args,
1190 const std::string &folder, const Twine &subfolder1, const Twine &subfolder2,
1191 const Twine &subfolder3) const {
1192 llvm::SmallString<128> path(folder);
1193 llvm::sys::path::append(path, subfolder1, subfolder2, subfolder3);
1194 addSystemInclude(DriverArgs, CC1Args, path);
1197 void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
1198 ArgStringList &CC1Args) const {
1199 if (DriverArgs.hasArg(options::OPT_nostdinc))
1202 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
1203 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, getDriver().ResourceDir,
1207 // Add %INCLUDE%-like directories from the -imsvc flag.
1208 for (const auto &Path : DriverArgs.getAllArgValues(options::OPT__SLASH_imsvc))
1209 addSystemInclude(DriverArgs, CC1Args, Path);
1211 if (DriverArgs.hasArg(options::OPT_nostdlibinc))
1214 // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat.
1215 if (llvm::Optional<std::string> cl_include_dir =
1216 llvm::sys::Process::GetEnv("INCLUDE")) {
1217 SmallVector<StringRef, 8> Dirs;
1218 StringRef(*cl_include_dir)
1219 .split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
1220 for (StringRef Dir : Dirs)
1221 addSystemInclude(DriverArgs, CC1Args, Dir);
1226 // When built with access to the proper Windows APIs, try to actually find
1227 // the correct include paths first.
1228 if (!VCToolChainPath.empty()) {
1229 addSystemInclude(DriverArgs, CC1Args,
1230 getSubDirectoryPath(SubDirectoryType::Include));
1232 if (useUniversalCRT()) {
1233 std::string UniversalCRTSdkPath;
1234 std::string UCRTVersion;
1235 if (getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion)) {
1236 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath,
1237 "Include", UCRTVersion, "ucrt");
1241 std::string WindowsSDKDir;
1243 std::string windowsSDKIncludeVersion;
1244 std::string windowsSDKLibVersion;
1245 if (getWindowsSDKDir(WindowsSDKDir, major, windowsSDKIncludeVersion,
1246 windowsSDKLibVersion)) {
1248 // Note: windowsSDKIncludeVersion is empty for SDKs prior to v10.
1249 // Anyway, llvm::sys::path::append is able to manage it.
1250 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
1251 "include", windowsSDKIncludeVersion,
1253 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
1254 "include", windowsSDKIncludeVersion,
1256 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
1257 "include", windowsSDKIncludeVersion,
1260 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
1269 // As a fallback, select default install paths.
1270 // FIXME: Don't guess drives and paths like this on Windows.
1271 const StringRef Paths[] = {
1272 "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
1273 "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
1274 "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
1275 "C:/Program Files/Microsoft Visual Studio 8/VC/include",
1276 "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
1278 addSystemIncludes(DriverArgs, CC1Args, Paths);
1282 void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
1283 ArgStringList &CC1Args) const {
1284 // FIXME: There should probably be logic here to find libc++ on Windows.
1287 VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D,
1288 const ArgList &Args) const {
1289 bool IsWindowsMSVC = getTriple().isWindowsMSVCEnvironment();
1290 VersionTuple MSVT = ToolChain::computeMSVCVersion(D, Args);
1292 MSVT = getMSVCVersionFromTriple(getTriple());
1293 if (MSVT.empty() && IsWindowsMSVC)
1294 MSVT = getMSVCVersionFromExe(getSubDirectoryPath(SubDirectoryType::Bin));
1296 Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
1298 // -fms-compatibility-version=19.11 is default, aka 2017, 15.3
1299 MSVT = VersionTuple(19, 11);
1305 MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
1306 types::ID InputType) const {
1307 // The MSVC version doesn't care about the architecture, even though it
1308 // may look at the triple internally.
1309 VersionTuple MSVT = computeMSVCVersion(/*D=*/nullptr, Args);
1310 MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().getValueOr(0),
1311 MSVT.getSubminor().getValueOr(0));
1313 // For the rest of the triple, however, a computed architecture name may
1315 llvm::Triple Triple(ToolChain::ComputeEffectiveClangTriple(Args, InputType));
1316 if (Triple.getEnvironment() == llvm::Triple::MSVC) {
1317 StringRef ObjFmt = Triple.getEnvironmentName().split('-').second;
1319 Triple.setEnvironmentName((Twine("msvc") + MSVT.getAsString()).str());
1321 Triple.setEnvironmentName(
1322 (Twine("msvc") + MSVT.getAsString() + Twine('-') + ObjFmt).str());
1324 return Triple.getTriple();
1327 SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
1328 SanitizerMask Res = ToolChain::getSupportedSanitizers();
1329 Res |= SanitizerKind::Address;
1330 Res |= SanitizerKind::PointerCompare;
1331 Res |= SanitizerKind::PointerSubtract;
1332 Res |= SanitizerKind::Fuzzer;
1333 Res |= SanitizerKind::FuzzerNoLink;
1334 Res &= ~SanitizerKind::CFIMFCall;
1338 static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL,
1339 bool SupportsForcingFramePointer,
1340 const char *ExpandChar, const OptTable &Opts) {
1341 assert(A->getOption().matches(options::OPT__SLASH_O));
1343 StringRef OptStr = A->getValue();
1344 for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
1345 const char &OptChar = *(OptStr.data() + I);
1353 // Ignore /O[12xd] flags that aren't the last one on the command line.
1354 // Only the last one gets expanded.
1355 if (&OptChar != ExpandChar) {
1359 if (OptChar == 'd') {
1360 DAL.AddFlagArg(A, Opts.getOption(options::OPT_O0));
1362 if (OptChar == '1') {
1363 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
1364 } else if (OptChar == '2' || OptChar == 'x') {
1365 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
1366 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
1368 if (SupportsForcingFramePointer &&
1369 !DAL.hasArgNoClaim(options::OPT_fno_omit_frame_pointer))
1370 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fomit_frame_pointer));
1371 if (OptChar == '1' || OptChar == '2')
1372 DAL.AddFlagArg(A, Opts.getOption(options::OPT_ffunction_sections));
1376 if (I + 1 != E && isdigit(OptStr[I + 1])) {
1377 switch (OptStr[I + 1]) {
1379 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_inline));
1382 DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_hint_functions));
1385 DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_functions));
1395 if (I + 1 != E && OptStr[I + 1] == '-') {
1397 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin));
1399 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
1403 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
1406 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
1409 bool OmitFramePointer = true;
1410 if (I + 1 != E && OptStr[I + 1] == '-') {
1411 OmitFramePointer = false;
1414 if (SupportsForcingFramePointer) {
1415 if (OmitFramePointer)
1417 Opts.getOption(options::OPT_fomit_frame_pointer));
1420 A, Opts.getOption(options::OPT_fno_omit_frame_pointer));
1422 // Don't warn about /Oy- in x86-64 builds (where
1423 // SupportsForcingFramePointer is false). The flag having no effect
1424 // there is a compiler-internal optimization, and people shouldn't have
1425 // to special-case their build files for x86-64 clang-cl.
1434 static void TranslateDArg(Arg *A, llvm::opt::DerivedArgList &DAL,
1435 const OptTable &Opts) {
1436 assert(A->getOption().matches(options::OPT_D));
1438 StringRef Val = A->getValue();
1439 size_t Hash = Val.find('#');
1440 if (Hash == StringRef::npos || Hash > Val.find('=')) {
1445 std::string NewVal = Val;
1447 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_D), NewVal);
1450 llvm::opt::DerivedArgList *
1451 MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
1452 StringRef BoundArch, Action::OffloadKind) const {
1453 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
1454 const OptTable &Opts = getDriver().getOpts();
1456 // /Oy and /Oy- don't have an effect on X86-64
1457 bool SupportsForcingFramePointer = getArch() != llvm::Triple::x86_64;
1459 // The -O[12xd] flag actually expands to several flags. We must desugar the
1460 // flags so that options embedded can be negated. For example, the '-O2' flag
1461 // enables '-Oy'. Expanding '-O2' into its constituent flags allows us to
1462 // correctly handle '-O2 -Oy-' where the trailing '-Oy-' disables a single
1465 // Note that this expansion logic only applies to the *last* of '[12xd]'.
1467 // First step is to search for the character we'd like to expand.
1468 const char *ExpandChar = nullptr;
1469 for (Arg *A : Args.filtered(options::OPT__SLASH_O)) {
1470 StringRef OptStr = A->getValue();
1471 for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
1472 char OptChar = OptStr[I];
1473 char PrevChar = I > 0 ? OptStr[I - 1] : '0';
1474 if (PrevChar == 'b') {
1475 // OptChar does not expand; it's an argument to the previous char.
1478 if (OptChar == '1' || OptChar == '2' || OptChar == 'x' || OptChar == 'd')
1479 ExpandChar = OptStr.data() + I;
1483 for (Arg *A : Args) {
1484 if (A->getOption().matches(options::OPT__SLASH_O)) {
1485 // The -O flag actually takes an amalgam of other options. For example,
1486 // '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'.
1487 TranslateOptArg(A, *DAL, SupportsForcingFramePointer, ExpandChar, Opts);
1488 } else if (A->getOption().matches(options::OPT_D)) {
1489 // Translate -Dfoo#bar into -Dfoo=bar.
1490 TranslateDArg(A, *DAL, Opts);