1 //===--- ToolChains.cpp - ToolChain Implementations -----------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 #include "CommonArgs.h"
13 #include "clang/Basic/CharInfo.h"
14 #include "clang/Basic/Version.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"
34 #define WIN32_LEAN_AND_MEAN
43 // Don't support SetupApi on MinGW.
44 #define USE_MSVC_SETUP_API
46 // Make sure this comes before MSVCSetupApi.h
49 #include "MSVCSetupApi.h"
50 #include "llvm/Support/COM.h"
51 _COM_SMARTPTR_TYPEDEF(ISetupConfiguration, __uuidof(ISetupConfiguration));
52 _COM_SMARTPTR_TYPEDEF(ISetupConfiguration2, __uuidof(ISetupConfiguration2));
53 _COM_SMARTPTR_TYPEDEF(ISetupHelper, __uuidof(ISetupHelper));
54 _COM_SMARTPTR_TYPEDEF(IEnumSetupInstances, __uuidof(IEnumSetupInstances));
55 _COM_SMARTPTR_TYPEDEF(ISetupInstance, __uuidof(ISetupInstance));
56 _COM_SMARTPTR_TYPEDEF(ISetupInstance2, __uuidof(ISetupInstance2));
59 using namespace clang::driver;
60 using namespace clang::driver::toolchains;
61 using namespace clang::driver::tools;
62 using namespace clang;
63 using namespace llvm::opt;
66 // Forward declare this so there aren't too many things above the constructor.
67 static bool getSystemRegistryString(const char *keyPath, const char *valueName,
68 std::string &value, std::string *phValue);
70 // Check various environment variables to try and find a toolchain.
71 static bool findVCToolChainViaEnvironment(std::string &Path,
72 MSVCToolChain::ToolsetLayout &VSLayout) {
73 // These variables are typically set by vcvarsall.bat
74 // when launching a developer command prompt.
75 if (llvm::Optional<std::string> VCToolsInstallDir =
76 llvm::sys::Process::GetEnv("VCToolsInstallDir")) {
77 // This is only set by newer Visual Studios, and it leads straight to
78 // the toolchain directory.
79 Path = std::move(*VCToolsInstallDir);
80 VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
83 if (llvm::Optional<std::string> VCInstallDir =
84 llvm::sys::Process::GetEnv("VCINSTALLDIR")) {
85 // If the previous variable isn't set but this one is, then we've found
86 // an older Visual Studio. This variable is set by newer Visual Studios too,
87 // so this check has to appear second.
88 // In older Visual Studios, the VC directory is the toolchain.
89 Path = std::move(*VCInstallDir);
90 VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
94 // We couldn't find any VC environment variables. Let's walk through PATH and
95 // see if it leads us to a VC toolchain bin directory. If it does, pick the
96 // first one that we find.
97 if (llvm::Optional<std::string> PathEnv =
98 llvm::sys::Process::GetEnv("PATH")) {
99 llvm::SmallVector<llvm::StringRef, 8> PathEntries;
100 llvm::StringRef(*PathEnv).split(PathEntries, llvm::sys::EnvPathSeparator);
101 for (llvm::StringRef PathEntry : PathEntries) {
102 if (PathEntry.empty())
105 llvm::SmallString<256> ExeTestPath;
107 // If cl.exe doesn't exist, then this definitely isn't a VC toolchain.
108 ExeTestPath = PathEntry;
109 llvm::sys::path::append(ExeTestPath, "cl.exe");
110 if (!llvm::sys::fs::exists(ExeTestPath))
113 // cl.exe existing isn't a conclusive test for a VC toolchain; clang also
114 // has a cl.exe. So let's check for link.exe too.
115 ExeTestPath = PathEntry;
116 llvm::sys::path::append(ExeTestPath, "link.exe");
117 if (!llvm::sys::fs::exists(ExeTestPath))
120 // whatever/VC/bin --> old toolchain, VC dir is toolchain dir.
121 llvm::StringRef TestPath = PathEntry;
122 bool IsBin = llvm::sys::path::filename(TestPath).equals_lower("bin");
124 // Strip any architecture subdir like "amd64".
125 TestPath = llvm::sys::path::parent_path(TestPath);
126 IsBin = llvm::sys::path::filename(TestPath).equals_lower("bin");
129 llvm::StringRef ParentPath = llvm::sys::path::parent_path(TestPath);
130 llvm::StringRef ParentFilename = llvm::sys::path::filename(ParentPath);
131 if (ParentFilename == "VC") {
133 VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
136 if (ParentFilename == "x86ret" || ParentFilename == "x86chk"
137 || ParentFilename == "amd64ret" || ParentFilename == "amd64chk") {
139 VSLayout = MSVCToolChain::ToolsetLayout::DevDivInternal;
144 // This could be a new (>=VS2017) toolchain. If it is, we should find
145 // path components with these prefixes when walking backwards through
147 // Note: empty strings match anything.
148 llvm::StringRef ExpectedPrefixes[] = {"", "Host", "bin", "",
149 "MSVC", "Tools", "VC"};
151 auto It = llvm::sys::path::rbegin(PathEntry);
152 auto End = llvm::sys::path::rend(PathEntry);
153 for (llvm::StringRef Prefix : ExpectedPrefixes) {
156 if (!It->startswith(Prefix))
161 // We've found a new toolchain!
162 // Back up 3 times (/bin/Host/arch) to get the root path.
163 llvm::StringRef ToolChainPath(PathEntry);
164 for (int i = 0; i < 3; ++i)
165 ToolChainPath = llvm::sys::path::parent_path(ToolChainPath);
167 Path = ToolChainPath;
168 VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
179 // Query the Setup Config server for installs, then pick the newest version
180 // and find its default VC toolchain.
181 // This is the preferred way to discover new Visual Studios, as they're no
182 // longer listed in the registry.
183 static bool findVCToolChainViaSetupConfig(std::string &Path,
184 MSVCToolChain::ToolsetLayout &VSLayout) {
185 #if !defined(USE_MSVC_SETUP_API)
188 // FIXME: This really should be done once in the top-level program's main
189 // function, as it may have already been initialized with a different
190 // threading model otherwise.
191 llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::SingleThreaded);
194 // _com_ptr_t will throw a _com_error if a COM calls fail.
195 // The LLVM coding standards forbid exception handling, so we'll have to
196 // stop them from being thrown in the first place.
197 // The destructor will put the regular error handler back when we leave
199 struct SuppressCOMErrorsRAII {
200 static void __stdcall handler(HRESULT hr, IErrorInfo *perrinfo) {}
202 SuppressCOMErrorsRAII() { _set_com_error_handler(handler); }
204 ~SuppressCOMErrorsRAII() { _set_com_error_handler(_com_raise_error); }
206 } COMErrorSuppressor;
208 ISetupConfigurationPtr Query;
209 HR = Query.CreateInstance(__uuidof(SetupConfiguration));
213 IEnumSetupInstancesPtr EnumInstances;
214 HR = ISetupConfiguration2Ptr(Query)->EnumAllInstances(&EnumInstances);
218 ISetupInstancePtr Instance;
219 HR = EnumInstances->Next(1, &Instance, nullptr);
223 ISetupInstancePtr NewestInstance;
224 Optional<uint64_t> NewestVersionNum;
226 bstr_t VersionString;
228 HR = Instance->GetInstallationVersion(VersionString.GetAddress());
231 HR = ISetupHelperPtr(Query)->ParseVersion(VersionString, &VersionNum);
234 if (!NewestVersionNum || (VersionNum > NewestVersionNum)) {
235 NewestInstance = Instance;
236 NewestVersionNum = VersionNum;
238 } while ((HR = EnumInstances->Next(1, &Instance, nullptr)) == S_OK);
244 HR = NewestInstance->ResolvePath(L"VC", VCPathWide.GetAddress());
248 std::string VCRootPath;
249 llvm::convertWideToUTF8(std::wstring(VCPathWide), VCRootPath);
251 llvm::SmallString<256> ToolsVersionFilePath(VCRootPath);
252 llvm::sys::path::append(ToolsVersionFilePath, "Auxiliary", "Build",
253 "Microsoft.VCToolsVersion.default.txt");
255 auto ToolsVersionFile = llvm::MemoryBuffer::getFile(ToolsVersionFilePath);
256 if (!ToolsVersionFile)
259 llvm::SmallString<256> ToolchainPath(VCRootPath);
260 llvm::sys::path::append(ToolchainPath, "Tools", "MSVC",
261 ToolsVersionFile->get()->getBuffer().rtrim());
262 if (!llvm::sys::fs::is_directory(ToolchainPath))
265 Path = ToolchainPath.str();
266 VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
271 // Look in the registry for Visual Studio installs, and use that to get
272 // a toolchain path. VS2017 and newer don't get added to the registry.
273 // So if we find something here, we know that it's an older version.
274 static bool findVCToolChainViaRegistry(std::string &Path,
275 MSVCToolChain::ToolsetLayout &VSLayout) {
276 std::string VSInstallPath;
277 if (getSystemRegistryString(R"(SOFTWARE\Microsoft\VisualStudio\$VERSION)",
278 "InstallDir", VSInstallPath, nullptr) ||
279 getSystemRegistryString(R"(SOFTWARE\Microsoft\VCExpress\$VERSION)",
280 "InstallDir", VSInstallPath, nullptr)) {
281 if (!VSInstallPath.empty()) {
282 llvm::SmallString<256> VCPath(llvm::StringRef(
283 VSInstallPath.c_str(), VSInstallPath.find(R"(\Common7\IDE)")));
284 llvm::sys::path::append(VCPath, "VC");
287 VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
294 // Try to find Exe from a Visual Studio distribution. This first tries to find
295 // an installed copy of Visual Studio and, failing that, looks in the PATH,
296 // making sure that whatever executable that's found is not a same-named exe
297 // from clang itself to prevent clang from falling back to itself.
298 static std::string FindVisualStudioExecutable(const ToolChain &TC,
300 const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC);
301 SmallString<128> FilePath(MSVC.getSubDirectoryPath(
302 toolchains::MSVCToolChain::SubDirectoryType::Bin));
303 llvm::sys::path::append(FilePath, Exe);
304 return llvm::sys::fs::can_execute(FilePath) ? FilePath.str() : Exe;
307 void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
308 const InputInfo &Output,
309 const InputInfoList &Inputs,
311 const char *LinkingOutput) const {
312 ArgStringList CmdArgs;
314 auto &TC = static_cast<const toolchains::MSVCToolChain &>(getToolChain());
316 assert((Output.isFilename() || Output.isNothing()) && "invalid output");
317 if (Output.isFilename())
319 Args.MakeArgString(std::string("-out:") + Output.getFilename()));
321 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) &&
322 !C.getDriver().IsCLMode())
323 CmdArgs.push_back("-defaultlib:libcmt");
325 if (!llvm::sys::Process::GetEnv("LIB")) {
326 // If the VC environment hasn't been configured (perhaps because the user
327 // did not run vcvarsall), try to build a consistent link environment. If
328 // the environment variable is set however, assume the user knows what
330 CmdArgs.push_back(Args.MakeArgString(
332 TC.getSubDirectoryPath(
333 toolchains::MSVCToolChain::SubDirectoryType::Lib)));
335 if (TC.useUniversalCRT()) {
336 std::string UniversalCRTLibPath;
337 if (TC.getUniversalCRTLibraryPath(UniversalCRTLibPath))
339 Args.MakeArgString(Twine("-libpath:") + UniversalCRTLibPath));
342 std::string WindowsSdkLibPath;
343 if (TC.getWindowsSDKLibraryPath(WindowsSdkLibPath))
345 Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath));
348 if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L))
349 for (const auto &LibPath : Args.getAllArgValues(options::OPT_L))
350 CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath));
352 CmdArgs.push_back("-nologo");
354 if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7,
355 options::OPT__SLASH_Zd))
356 CmdArgs.push_back("-debug");
358 // Pass on /Brepro if it was passed to the compiler.
359 // Note that /Brepro maps to -mno-incremental-linker-compatible.
360 bool DefaultIncrementalLinkerCompatible =
361 C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment();
362 if (!Args.hasFlag(options::OPT_mincremental_linker_compatible,
363 options::OPT_mno_incremental_linker_compatible,
364 DefaultIncrementalLinkerCompatible))
365 CmdArgs.push_back("-Brepro");
367 bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd,
368 options::OPT_shared);
370 CmdArgs.push_back(Args.MakeArgString("-dll"));
372 SmallString<128> ImplibName(Output.getFilename());
373 llvm::sys::path::replace_extension(ImplibName, "lib");
374 CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName));
377 if (TC.getSanitizerArgs().needsFuzzer()) {
378 if (!Args.hasArg(options::OPT_shared))
380 Args.MakeArgString(std::string("-wholearchive:") +
381 TC.getCompilerRTArgString(Args, "fuzzer", false)));
382 CmdArgs.push_back(Args.MakeArgString("-debug"));
383 // Prevent the linker from padding sections we use for instrumentation
385 CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
388 if (TC.getSanitizerArgs().needsAsanRt()) {
389 CmdArgs.push_back(Args.MakeArgString("-debug"));
390 CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
391 if (TC.getSanitizerArgs().needsSharedRt() ||
392 Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
393 for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
394 CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
395 // Make sure the dynamic runtime thunk is not optimized out at link time
396 // to ensure proper SEH handling.
397 CmdArgs.push_back(Args.MakeArgString(
398 TC.getArch() == llvm::Triple::x86
399 ? "-include:___asan_seh_interceptor"
400 : "-include:__asan_seh_interceptor"));
401 // Make sure the linker consider all object files from the dynamic runtime
403 CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
404 TC.getCompilerRT(Args, "asan_dynamic_runtime_thunk")));
406 CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
408 for (const auto &Lib : {"asan", "asan_cxx"}) {
409 CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
410 // Make sure the linker consider all object files from the static lib.
411 // This is necessary because instrumented dlls need access to all the
412 // interface exported by the static lib in the main executable.
413 CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
414 TC.getCompilerRT(Args, Lib)));
419 Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link);
421 if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
422 options::OPT_fno_openmp, false)) {
423 CmdArgs.push_back("-nodefaultlib:vcomp.lib");
424 CmdArgs.push_back("-nodefaultlib:vcompd.lib");
425 CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
426 TC.getDriver().Dir + "/../lib"));
427 switch (TC.getDriver().getOpenMPRuntime(Args)) {
428 case Driver::OMPRT_OMP:
429 CmdArgs.push_back("-defaultlib:libomp.lib");
431 case Driver::OMPRT_IOMP5:
432 CmdArgs.push_back("-defaultlib:libiomp5md.lib");
434 case Driver::OMPRT_GOMP:
436 case Driver::OMPRT_Unknown:
437 // Already diagnosed.
442 // Add compiler-rt lib in case if it was explicitly
443 // specified as an argument for --rtlib option.
444 if (!Args.hasArg(options::OPT_nostdlib)) {
445 AddRunTimeLibs(TC, TC.getDriver(), CmdArgs, Args);
448 // Add filenames, libraries, and other linker inputs.
449 for (const auto &Input : Inputs) {
450 if (Input.isFilename()) {
451 CmdArgs.push_back(Input.getFilename());
455 const Arg &A = Input.getInputArg();
457 // Render -l options differently for the MSVC linker.
458 if (A.getOption().matches(options::OPT_l)) {
459 StringRef Lib = A.getValue();
460 const char *LinkLibArg;
461 if (Lib.endswith(".lib"))
462 LinkLibArg = Args.MakeArgString(Lib);
464 LinkLibArg = Args.MakeArgString(Lib + ".lib");
465 CmdArgs.push_back(LinkLibArg);
469 // Otherwise, this is some other kind of linker input option like -Wl, -z,
470 // or -L. Render it, even if MSVC doesn't understand it.
471 A.renderAsInput(Args, CmdArgs);
474 TC.addProfileRTLibs(Args, CmdArgs);
476 std::vector<const char *> Environment;
478 // We need to special case some linker paths. In the case of lld, we need to
479 // translate 'lld' into 'lld-link', and in the case of the regular msvc
480 // linker, we need to use a special search algorithm.
481 llvm::SmallString<128> linkPath;
482 StringRef Linker = Args.getLastArgValue(options::OPT_fuse_ld_EQ, "link");
483 if (Linker.equals_lower("lld"))
486 if (Linker.equals_lower("link")) {
487 // If we're using the MSVC linker, it's not sufficient to just use link
488 // from the program PATH, because other environments like GnuWin32 install
489 // their own link.exe which may come first.
490 linkPath = FindVisualStudioExecutable(TC, "link.exe");
492 if (!TC.FoundMSVCInstall() && !llvm::sys::fs::can_execute(linkPath))
493 C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
496 // When cross-compiling with VS2017 or newer, link.exe expects to have
497 // its containing bin directory at the top of PATH, followed by the
498 // native target bin directory.
499 // e.g. when compiling for x86 on an x64 host, PATH should start with:
500 // /bin/HostX64/x86;/bin/HostX64/x64
501 // This doesn't attempt to handle ToolsetLayout::DevDivInternal.
502 if (TC.getIsVS2017OrNewer() &&
503 llvm::Triple(llvm::sys::getProcessTriple()).getArch() != TC.getArch()) {
504 auto HostArch = llvm::Triple(llvm::sys::getProcessTriple()).getArch();
507 std::unique_ptr<wchar_t[], decltype(&FreeEnvironmentStringsW)>(
508 GetEnvironmentStringsW(), FreeEnvironmentStringsW);
510 goto SkipSettingEnvironment;
513 size_t EnvBlockLen = 0;
514 while (EnvBlockWide[EnvBlockLen] != L'\0') {
516 EnvBlockLen += std::wcslen(&EnvBlockWide[EnvBlockLen]) +
517 1 /*string null-terminator*/;
519 ++EnvBlockLen; // add the block null-terminator
521 std::string EnvBlock;
522 if (!llvm::convertUTF16ToUTF8String(
523 llvm::ArrayRef<char>(reinterpret_cast<char *>(EnvBlockWide.get()),
524 EnvBlockLen * sizeof(EnvBlockWide[0])),
526 goto SkipSettingEnvironment;
528 Environment.reserve(EnvCount);
530 // Now loop over each string in the block and copy them into the
531 // environment vector, adjusting the PATH variable as needed when we
533 for (const char *Cursor = EnvBlock.data(); *Cursor != '\0';) {
534 llvm::StringRef EnvVar(Cursor);
535 if (EnvVar.startswith_lower("path=")) {
536 using SubDirectoryType = toolchains::MSVCToolChain::SubDirectoryType;
537 constexpr size_t PrefixLen = 5; // strlen("path=")
538 Environment.push_back(Args.MakeArgString(
539 EnvVar.substr(0, PrefixLen) +
540 TC.getSubDirectoryPath(SubDirectoryType::Bin) +
541 llvm::Twine(llvm::sys::EnvPathSeparator) +
542 TC.getSubDirectoryPath(SubDirectoryType::Bin, HostArch) +
543 (EnvVar.size() > PrefixLen
544 ? llvm::Twine(llvm::sys::EnvPathSeparator) +
545 EnvVar.substr(PrefixLen)
548 Environment.push_back(Args.MakeArgString(EnvVar));
550 Cursor += EnvVar.size() + 1 /*null-terminator*/;
553 SkipSettingEnvironment:;
556 linkPath = TC.GetProgramPath(Linker.str().c_str());
559 auto LinkCmd = llvm::make_unique<Command>(
560 JA, *this, Args.MakeArgString(linkPath), CmdArgs, Inputs);
561 if (!Environment.empty())
562 LinkCmd->setEnvironment(Environment);
563 C.addCommand(std::move(LinkCmd));
566 void visualstudio::Compiler::ConstructJob(Compilation &C, const JobAction &JA,
567 const InputInfo &Output,
568 const InputInfoList &Inputs,
570 const char *LinkingOutput) const {
571 C.addCommand(GetCommand(C, JA, Output, Inputs, Args, LinkingOutput));
574 std::unique_ptr<Command> visualstudio::Compiler::GetCommand(
575 Compilation &C, const JobAction &JA, const InputInfo &Output,
576 const InputInfoList &Inputs, const ArgList &Args,
577 const char *LinkingOutput) const {
578 ArgStringList CmdArgs;
579 CmdArgs.push_back("/nologo");
580 CmdArgs.push_back("/c"); // Compile only.
581 CmdArgs.push_back("/W0"); // No warnings.
583 // The goal is to be able to invoke this tool correctly based on
584 // any flag accepted by clang-cl.
586 // These are spelled the same way in clang and cl.exe,.
587 Args.AddAllArgs(CmdArgs, {options::OPT_D, options::OPT_U, options::OPT_I});
589 // Optimization level.
590 if (Arg *A = Args.getLastArg(options::OPT_fbuiltin, options::OPT_fno_builtin))
591 CmdArgs.push_back(A->getOption().getID() == options::OPT_fbuiltin ? "/Oi"
593 if (Arg *A = Args.getLastArg(options::OPT_O, options::OPT_O0)) {
594 if (A->getOption().getID() == options::OPT_O0) {
595 CmdArgs.push_back("/Od");
597 CmdArgs.push_back("/Og");
599 StringRef OptLevel = A->getValue();
600 if (OptLevel == "s" || OptLevel == "z")
601 CmdArgs.push_back("/Os");
603 CmdArgs.push_back("/Ot");
605 CmdArgs.push_back("/Ob2");
608 if (Arg *A = Args.getLastArg(options::OPT_fomit_frame_pointer,
609 options::OPT_fno_omit_frame_pointer))
610 CmdArgs.push_back(A->getOption().getID() == options::OPT_fomit_frame_pointer
613 if (!Args.hasArg(options::OPT_fwritable_strings))
614 CmdArgs.push_back("/GF");
616 // Flags for which clang-cl has an alias.
617 // FIXME: How can we ensure this stays in sync with relevant clang-cl options?
619 if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR,
621 CmdArgs.push_back("/GR-");
623 if (Args.hasFlag(options::OPT__SLASH_GS_, options::OPT__SLASH_GS,
625 CmdArgs.push_back("/GS-");
627 if (Arg *A = Args.getLastArg(options::OPT_ffunction_sections,
628 options::OPT_fno_function_sections))
629 CmdArgs.push_back(A->getOption().getID() == options::OPT_ffunction_sections
632 if (Arg *A = Args.getLastArg(options::OPT_fdata_sections,
633 options::OPT_fno_data_sections))
635 A->getOption().getID() == options::OPT_fdata_sections ? "/Gw" : "/Gw-");
636 if (Args.hasArg(options::OPT_fsyntax_only))
637 CmdArgs.push_back("/Zs");
638 if (Args.hasArg(options::OPT_g_Flag, options::OPT_gline_tables_only,
639 options::OPT__SLASH_Z7))
640 CmdArgs.push_back("/Z7");
642 std::vector<std::string> Includes =
643 Args.getAllArgValues(options::OPT_include);
644 for (const auto &Include : Includes)
645 CmdArgs.push_back(Args.MakeArgString(std::string("/FI") + Include));
647 // Flags that can simply be passed through.
648 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LD);
649 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LDd);
650 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_GX);
651 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_GX_);
652 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_EH);
653 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_Zl);
655 // The order of these flags is relevant, so pick the last one.
656 if (Arg *A = Args.getLastArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd,
657 options::OPT__SLASH_MT, options::OPT__SLASH_MTd))
658 A->render(Args, CmdArgs);
660 // Use MSVC's default threadsafe statics behaviour unless there was a flag.
661 if (Arg *A = Args.getLastArg(options::OPT_fthreadsafe_statics,
662 options::OPT_fno_threadsafe_statics)) {
663 CmdArgs.push_back(A->getOption().getID() == options::OPT_fthreadsafe_statics
664 ? "/Zc:threadSafeInit"
665 : "/Zc:threadSafeInit-");
668 // Pass through all unknown arguments so that the fallback command can see
670 Args.AddAllArgs(CmdArgs, options::OPT_UNKNOWN);
673 assert(Inputs.size() == 1);
674 const InputInfo &II = Inputs[0];
675 assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX);
676 CmdArgs.push_back(II.getType() == types::TY_C ? "/Tc" : "/Tp");
678 CmdArgs.push_back(II.getFilename());
680 II.getInputArg().renderAsInput(Args, CmdArgs);
683 assert(Output.getType() == types::TY_Object);
685 Args.MakeArgString(std::string("/Fo") + Output.getFilename());
686 CmdArgs.push_back(Fo);
688 std::string Exec = FindVisualStudioExecutable(getToolChain(), "cl.exe");
689 return llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
693 MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
695 : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args) {
696 getProgramPaths().push_back(getDriver().getInstalledDir());
697 if (getDriver().getInstalledDir() != getDriver().Dir)
698 getProgramPaths().push_back(getDriver().Dir);
700 // Check the environment first, since that's probably the user telling us
701 // what they want to use.
702 // Failing that, just try to find the newest Visual Studio version we can
703 // and use its default VC toolchain.
704 findVCToolChainViaEnvironment(VCToolChainPath, VSLayout) ||
705 findVCToolChainViaSetupConfig(VCToolChainPath, VSLayout) ||
706 findVCToolChainViaRegistry(VCToolChainPath, VSLayout);
709 Tool *MSVCToolChain::buildLinker() const {
710 return new tools::visualstudio::Linker(*this);
713 Tool *MSVCToolChain::buildAssembler() const {
714 if (getTriple().isOSBinFormatMachO())
715 return new tools::darwin::Assembler(*this);
716 getDriver().Diag(clang::diag::err_no_external_assembler);
720 bool MSVCToolChain::IsIntegratedAssemblerDefault() const {
724 bool MSVCToolChain::IsUnwindTablesDefault(const ArgList &Args) const {
725 // Don't emit unwind tables by default for MachO targets.
726 if (getTriple().isOSBinFormatMachO())
729 // All non-x86_32 Windows targets require unwind tables. However, LLVM
730 // doesn't know how to generate them for all targets, so only enable
731 // the ones that are actually implemented.
732 return getArch() == llvm::Triple::x86_64 ||
733 getArch() == llvm::Triple::aarch64;
736 bool MSVCToolChain::isPICDefault() const {
737 return getArch() == llvm::Triple::x86_64;
740 bool MSVCToolChain::isPIEDefault() const {
744 bool MSVCToolChain::isPICDefaultForced() const {
745 return getArch() == llvm::Triple::x86_64;
748 void MSVCToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
749 ArgStringList &CC1Args) const {
750 CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
753 void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const {
754 CudaInstallation.print(OS);
757 // Windows SDKs and VC Toolchains group their contents into subdirectories based
758 // on the target architecture. This function converts an llvm::Triple::ArchType
759 // to the corresponding subdirectory name.
760 static const char *llvmArchToWindowsSDKArch(llvm::Triple::ArchType Arch) {
761 using ArchType = llvm::Triple::ArchType;
765 case ArchType::x86_64:
769 case ArchType::aarch64:
776 // Similar to the above function, but for Visual Studios before VS2017.
777 static const char *llvmArchToLegacyVCArch(llvm::Triple::ArchType Arch) {
778 using ArchType = llvm::Triple::ArchType;
781 // x86 is default in legacy VC toolchains.
782 // e.g. x86 libs are directly in /lib as opposed to /lib/x86.
784 case ArchType::x86_64:
788 case ArchType::aarch64:
795 // Similar to the above function, but for DevDiv internal builds.
796 static const char *llvmArchToDevDivInternalArch(llvm::Triple::ArchType Arch) {
797 using ArchType = llvm::Triple::ArchType;
801 case ArchType::x86_64:
805 case ArchType::aarch64:
812 // Get the path to a specific subdirectory in the current toolchain for
813 // a given target architecture.
814 // VS2017 changed the VC toolchain layout, so this should be used instead
815 // of hardcoding paths.
817 MSVCToolChain::getSubDirectoryPath(SubDirectoryType Type,
818 llvm::Triple::ArchType TargetArch) const {
819 const char *SubdirName;
820 const char *IncludeName;
822 case ToolsetLayout::OlderVS:
823 SubdirName = llvmArchToLegacyVCArch(TargetArch);
824 IncludeName = "include";
826 case ToolsetLayout::VS2017OrNewer:
827 SubdirName = llvmArchToWindowsSDKArch(TargetArch);
828 IncludeName = "include";
830 case ToolsetLayout::DevDivInternal:
831 SubdirName = llvmArchToDevDivInternalArch(TargetArch);
836 llvm::SmallString<256> Path(VCToolChainPath);
838 case SubDirectoryType::Bin:
839 if (VSLayout == ToolsetLayout::VS2017OrNewer) {
840 const bool HostIsX64 =
841 llvm::Triple(llvm::sys::getProcessTriple()).isArch64Bit();
842 const char *const HostName = HostIsX64 ? "HostX64" : "HostX86";
843 llvm::sys::path::append(Path, "bin", HostName, SubdirName);
844 } else { // OlderVS or DevDivInternal
845 llvm::sys::path::append(Path, "bin", SubdirName);
848 case SubDirectoryType::Include:
849 llvm::sys::path::append(Path, IncludeName);
851 case SubDirectoryType::Lib:
852 llvm::sys::path::append(Path, "lib", SubdirName);
859 static bool readFullStringValue(HKEY hkey, const char *valueName,
860 std::string &value) {
861 std::wstring WideValueName;
862 if (!llvm::ConvertUTF8toWide(valueName, WideValueName))
868 // First just query for the required size.
869 result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, &type, NULL,
871 if (result != ERROR_SUCCESS || type != REG_SZ || !valueSize)
873 std::vector<BYTE> buffer(valueSize);
874 result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, NULL, &buffer[0],
876 if (result == ERROR_SUCCESS) {
877 std::wstring WideValue(reinterpret_cast<const wchar_t *>(buffer.data()),
878 valueSize / sizeof(wchar_t));
879 if (valueSize && WideValue.back() == L'\0') {
880 WideValue.pop_back();
882 // The destination buffer must be empty as an invariant of the conversion
883 // function; but this function is sometimes called in a loop that passes in
884 // the same buffer, however. Simply clear it out so we can overwrite it.
886 return llvm::convertWideToUTF8(WideValue, value);
892 /// Read registry string.
893 /// This also supports a means to look for high-versioned keys by use
894 /// of a $VERSION placeholder in the key path.
895 /// $VERSION in the key path is a placeholder for the version number,
896 /// causing the highest value path to be searched for and used.
897 /// I.e. "SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
898 /// There can be additional characters in the component. Only the numeric
899 /// characters are compared. This function only searches HKLM.
900 static bool getSystemRegistryString(const char *keyPath, const char *valueName,
901 std::string &value, std::string *phValue) {
905 HKEY hRootKey = HKEY_LOCAL_MACHINE;
908 bool returnValue = false;
910 const char *placeHolder = strstr(keyPath, "$VERSION");
911 std::string bestName;
912 // If we have a $VERSION placeholder, do the highest-version search.
914 const char *keyEnd = placeHolder - 1;
915 const char *nextKey = placeHolder;
916 // Find end of previous key.
917 while ((keyEnd > keyPath) && (*keyEnd != '\\'))
919 // Find end of key containing $VERSION.
920 while (*nextKey && (*nextKey != '\\'))
922 size_t partialKeyLength = keyEnd - keyPath;
923 char partialKey[256];
924 if (partialKeyLength >= sizeof(partialKey))
925 partialKeyLength = sizeof(partialKey) - 1;
926 strncpy(partialKey, keyPath, partialKeyLength);
927 partialKey[partialKeyLength] = '\0';
929 lResult = RegOpenKeyExA(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY,
931 if (lResult == ERROR_SUCCESS) {
933 double bestValue = 0.0;
934 DWORD index, size = sizeof(keyName) - 1;
935 for (index = 0; RegEnumKeyExA(hTopKey, index, keyName, &size, NULL, NULL,
936 NULL, NULL) == ERROR_SUCCESS;
938 const char *sp = keyName;
939 while (*sp && !isDigit(*sp))
943 const char *ep = sp + 1;
944 while (*ep && (isDigit(*ep) || (*ep == '.')))
947 strncpy(numBuf, sp, sizeof(numBuf) - 1);
948 numBuf[sizeof(numBuf) - 1] = '\0';
949 double dvalue = strtod(numBuf, NULL);
950 if (dvalue > bestValue) {
951 // Test that InstallDir is indeed there before keeping this index.
952 // Open the chosen key path remainder.
954 // Append rest of key.
955 bestName.append(nextKey);
956 lResult = RegOpenKeyExA(hTopKey, bestName.c_str(), 0,
957 KEY_READ | KEY_WOW64_32KEY, &hKey);
958 if (lResult == ERROR_SUCCESS) {
959 if (readFullStringValue(hKey, valueName, value)) {
968 size = sizeof(keyName) - 1;
970 RegCloseKey(hTopKey);
974 RegOpenKeyExA(hRootKey, keyPath, 0, KEY_READ | KEY_WOW64_32KEY, &hKey);
975 if (lResult == ERROR_SUCCESS) {
976 if (readFullStringValue(hKey, valueName, value))
987 // Find the most recent version of Universal CRT or Windows 10 SDK.
988 // vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include
989 // directory by name and uses the last one of the list.
990 // So we compare entry names lexicographically to find the greatest one.
991 static bool getWindows10SDKVersionFromPath(const std::string &SDKPath,
992 std::string &SDKVersion) {
996 llvm::SmallString<128> IncludePath(SDKPath);
997 llvm::sys::path::append(IncludePath, "Include");
998 for (llvm::sys::fs::directory_iterator DirIt(IncludePath, EC), DirEnd;
999 DirIt != DirEnd && !EC; DirIt.increment(EC)) {
1000 if (!llvm::sys::fs::is_directory(DirIt->path()))
1002 StringRef CandidateName = llvm::sys::path::filename(DirIt->path());
1003 // If WDK is installed, there could be subfolders like "wdf" in the
1004 // "Include" directory.
1005 // Allow only directories which names start with "10.".
1006 if (!CandidateName.startswith("10."))
1008 if (CandidateName > SDKVersion)
1009 SDKVersion = CandidateName;
1012 return !SDKVersion.empty();
1015 /// Get Windows SDK installation directory.
1016 static bool getWindowsSDKDir(std::string &Path, int &Major,
1017 std::string &WindowsSDKIncludeVersion,
1018 std::string &WindowsSDKLibVersion) {
1019 std::string RegistrySDKVersion;
1020 // Try the Windows registry.
1021 if (!getSystemRegistryString(
1022 "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
1023 "InstallationFolder", Path, &RegistrySDKVersion))
1025 if (Path.empty() || RegistrySDKVersion.empty())
1028 WindowsSDKIncludeVersion.clear();
1029 WindowsSDKLibVersion.clear();
1031 std::sscanf(RegistrySDKVersion.c_str(), "v%d.", &Major);
1035 // Windows SDK 8.x installs libraries in a folder whose names depend on the
1036 // version of the OS you're targeting. By default choose the newest, which
1037 // usually corresponds to the version of the OS you've installed the SDK on.
1038 const char *Tests[] = {"winv6.3", "win8", "win7"};
1039 for (const char *Test : Tests) {
1040 llvm::SmallString<128> TestPath(Path);
1041 llvm::sys::path::append(TestPath, "Lib", Test);
1042 if (llvm::sys::fs::exists(TestPath.c_str())) {
1043 WindowsSDKLibVersion = Test;
1047 return !WindowsSDKLibVersion.empty();
1050 if (!getWindows10SDKVersionFromPath(Path, WindowsSDKIncludeVersion))
1052 WindowsSDKLibVersion = WindowsSDKIncludeVersion;
1055 // Unsupported SDK version
1059 // Gets the library path required to link against the Windows SDK.
1060 bool MSVCToolChain::getWindowsSDKLibraryPath(std::string &path) const {
1061 std::string sdkPath;
1063 std::string windowsSDKIncludeVersion;
1064 std::string windowsSDKLibVersion;
1067 if (!getWindowsSDKDir(sdkPath, sdkMajor, windowsSDKIncludeVersion,
1068 windowsSDKLibVersion))
1071 llvm::SmallString<128> libPath(sdkPath);
1072 llvm::sys::path::append(libPath, "Lib");
1073 if (sdkMajor >= 8) {
1074 llvm::sys::path::append(libPath, windowsSDKLibVersion, "um",
1075 llvmArchToWindowsSDKArch(getArch()));
1077 switch (getArch()) {
1078 // In Windows SDK 7.x, x86 libraries are directly in the Lib folder.
1079 case llvm::Triple::x86:
1081 case llvm::Triple::x86_64:
1082 llvm::sys::path::append(libPath, "x64");
1084 case llvm::Triple::arm:
1085 // It is not necessary to link against Windows SDK 7.x when targeting ARM.
1092 path = libPath.str();
1096 // Check if the Include path of a specified version of Visual Studio contains
1097 // specific header files. If not, they are probably shipped with Universal CRT.
1098 bool MSVCToolChain::useUniversalCRT() const {
1099 llvm::SmallString<128> TestPath(
1100 getSubDirectoryPath(SubDirectoryType::Include));
1101 llvm::sys::path::append(TestPath, "stdlib.h");
1102 return !llvm::sys::fs::exists(TestPath);
1105 static bool getUniversalCRTSdkDir(std::string &Path, std::string &UCRTVersion) {
1106 // vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry
1107 // for the specific key "KitsRoot10". So do we.
1108 if (!getSystemRegistryString(
1109 "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10",
1113 return getWindows10SDKVersionFromPath(Path, UCRTVersion);
1116 bool MSVCToolChain::getUniversalCRTLibraryPath(std::string &Path) const {
1117 std::string UniversalCRTSdkPath;
1118 std::string UCRTVersion;
1121 if (!getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion))
1124 StringRef ArchName = llvmArchToWindowsSDKArch(getArch());
1125 if (ArchName.empty())
1128 llvm::SmallString<128> LibPath(UniversalCRTSdkPath);
1129 llvm::sys::path::append(LibPath, "Lib", UCRTVersion, "ucrt", ArchName);
1131 Path = LibPath.str();
1135 static VersionTuple getMSVCVersionFromTriple(const llvm::Triple &Triple) {
1136 unsigned Major, Minor, Micro;
1137 Triple.getEnvironmentVersion(Major, Minor, Micro);
1138 if (Major || Minor || Micro)
1139 return VersionTuple(Major, Minor, Micro);
1140 return VersionTuple();
1143 static VersionTuple getMSVCVersionFromExe(const std::string &BinDir) {
1144 VersionTuple Version;
1146 SmallString<128> ClExe(BinDir);
1147 llvm::sys::path::append(ClExe, "cl.exe");
1149 std::wstring ClExeWide;
1150 if (!llvm::ConvertUTF8toWide(ClExe.c_str(), ClExeWide))
1153 const DWORD VersionSize = ::GetFileVersionInfoSizeW(ClExeWide.c_str(),
1155 if (VersionSize == 0)
1158 SmallVector<uint8_t, 4 * 1024> VersionBlock(VersionSize);
1159 if (!::GetFileVersionInfoW(ClExeWide.c_str(), 0, VersionSize,
1160 VersionBlock.data()))
1163 VS_FIXEDFILEINFO *FileInfo = nullptr;
1164 UINT FileInfoSize = 0;
1165 if (!::VerQueryValueW(VersionBlock.data(), L"\\",
1166 reinterpret_cast<LPVOID *>(&FileInfo), &FileInfoSize) ||
1167 FileInfoSize < sizeof(*FileInfo))
1170 const unsigned Major = (FileInfo->dwFileVersionMS >> 16) & 0xFFFF;
1171 const unsigned Minor = (FileInfo->dwFileVersionMS ) & 0xFFFF;
1172 const unsigned Micro = (FileInfo->dwFileVersionLS >> 16) & 0xFFFF;
1174 Version = VersionTuple(Major, Minor, Micro);
1179 void MSVCToolChain::AddSystemIncludeWithSubfolder(
1180 const ArgList &DriverArgs, ArgStringList &CC1Args,
1181 const std::string &folder, const Twine &subfolder1, const Twine &subfolder2,
1182 const Twine &subfolder3) const {
1183 llvm::SmallString<128> path(folder);
1184 llvm::sys::path::append(path, subfolder1, subfolder2, subfolder3);
1185 addSystemInclude(DriverArgs, CC1Args, path);
1188 void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
1189 ArgStringList &CC1Args) const {
1190 if (DriverArgs.hasArg(options::OPT_nostdinc))
1193 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
1194 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, getDriver().ResourceDir,
1198 // Add %INCLUDE%-like directories from the -imsvc flag.
1199 for (const auto &Path : DriverArgs.getAllArgValues(options::OPT__SLASH_imsvc))
1200 addSystemInclude(DriverArgs, CC1Args, Path);
1202 if (DriverArgs.hasArg(options::OPT_nostdlibinc))
1205 // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat.
1206 if (llvm::Optional<std::string> cl_include_dir =
1207 llvm::sys::Process::GetEnv("INCLUDE")) {
1208 SmallVector<StringRef, 8> Dirs;
1209 StringRef(*cl_include_dir)
1210 .split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
1211 for (StringRef Dir : Dirs)
1212 addSystemInclude(DriverArgs, CC1Args, Dir);
1217 // When built with access to the proper Windows APIs, try to actually find
1218 // the correct include paths first.
1219 if (!VCToolChainPath.empty()) {
1220 addSystemInclude(DriverArgs, CC1Args,
1221 getSubDirectoryPath(SubDirectoryType::Include));
1223 if (useUniversalCRT()) {
1224 std::string UniversalCRTSdkPath;
1225 std::string UCRTVersion;
1226 if (getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion)) {
1227 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath,
1228 "Include", UCRTVersion, "ucrt");
1232 std::string WindowsSDKDir;
1234 std::string windowsSDKIncludeVersion;
1235 std::string windowsSDKLibVersion;
1236 if (getWindowsSDKDir(WindowsSDKDir, major, windowsSDKIncludeVersion,
1237 windowsSDKLibVersion)) {
1239 // Note: windowsSDKIncludeVersion is empty for SDKs prior to v10.
1240 // Anyway, llvm::sys::path::append is able to manage it.
1241 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
1242 "include", windowsSDKIncludeVersion,
1244 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
1245 "include", windowsSDKIncludeVersion,
1247 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
1248 "include", windowsSDKIncludeVersion,
1251 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
1260 // As a fallback, select default install paths.
1261 // FIXME: Don't guess drives and paths like this on Windows.
1262 const StringRef Paths[] = {
1263 "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
1264 "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
1265 "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
1266 "C:/Program Files/Microsoft Visual Studio 8/VC/include",
1267 "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
1269 addSystemIncludes(DriverArgs, CC1Args, Paths);
1273 void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
1274 ArgStringList &CC1Args) const {
1275 // FIXME: There should probably be logic here to find libc++ on Windows.
1278 VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D,
1279 const ArgList &Args) const {
1280 bool IsWindowsMSVC = getTriple().isWindowsMSVCEnvironment();
1281 VersionTuple MSVT = ToolChain::computeMSVCVersion(D, Args);
1283 MSVT = getMSVCVersionFromTriple(getTriple());
1284 if (MSVT.empty() && IsWindowsMSVC)
1285 MSVT = getMSVCVersionFromExe(getSubDirectoryPath(SubDirectoryType::Bin));
1287 Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
1289 // -fms-compatibility-version=19.11 is default, aka 2017, 15.3
1290 MSVT = VersionTuple(19, 11);
1296 MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
1297 types::ID InputType) const {
1298 // The MSVC version doesn't care about the architecture, even though it
1299 // may look at the triple internally.
1300 VersionTuple MSVT = computeMSVCVersion(/*D=*/nullptr, Args);
1301 MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().getValueOr(0),
1302 MSVT.getSubminor().getValueOr(0));
1304 // For the rest of the triple, however, a computed architecture name may
1306 llvm::Triple Triple(ToolChain::ComputeEffectiveClangTriple(Args, InputType));
1307 if (Triple.getEnvironment() == llvm::Triple::MSVC) {
1308 StringRef ObjFmt = Triple.getEnvironmentName().split('-').second;
1310 Triple.setEnvironmentName((Twine("msvc") + MSVT.getAsString()).str());
1312 Triple.setEnvironmentName(
1313 (Twine("msvc") + MSVT.getAsString() + Twine('-') + ObjFmt).str());
1315 return Triple.getTriple();
1318 SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
1319 SanitizerMask Res = ToolChain::getSupportedSanitizers();
1320 Res |= SanitizerKind::Address;
1321 Res |= SanitizerKind::Fuzzer;
1322 Res |= SanitizerKind::FuzzerNoLink;
1323 Res &= ~SanitizerKind::CFIMFCall;
1327 static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL,
1328 bool SupportsForcingFramePointer,
1329 const char *ExpandChar, const OptTable &Opts) {
1330 assert(A->getOption().matches(options::OPT__SLASH_O));
1332 StringRef OptStr = A->getValue();
1333 for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
1334 const char &OptChar = *(OptStr.data() + I);
1342 // Ignore /O[12xd] flags that aren't the last one on the command line.
1343 // Only the last one gets expanded.
1344 if (&OptChar != ExpandChar) {
1348 if (OptChar == 'd') {
1349 DAL.AddFlagArg(A, Opts.getOption(options::OPT_O0));
1351 if (OptChar == '1') {
1352 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
1353 } else if (OptChar == '2' || OptChar == 'x') {
1354 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
1355 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
1357 if (SupportsForcingFramePointer &&
1358 !DAL.hasArgNoClaim(options::OPT_fno_omit_frame_pointer))
1359 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fomit_frame_pointer));
1360 if (OptChar == '1' || OptChar == '2')
1361 DAL.AddFlagArg(A, Opts.getOption(options::OPT_ffunction_sections));
1365 if (I + 1 != E && isdigit(OptStr[I + 1])) {
1366 switch (OptStr[I + 1]) {
1368 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_inline));
1371 DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_hint_functions));
1374 DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_functions));
1384 if (I + 1 != E && OptStr[I + 1] == '-') {
1386 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin));
1388 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
1392 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
1395 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
1398 bool OmitFramePointer = true;
1399 if (I + 1 != E && OptStr[I + 1] == '-') {
1400 OmitFramePointer = false;
1403 if (SupportsForcingFramePointer) {
1404 if (OmitFramePointer)
1406 Opts.getOption(options::OPT_fomit_frame_pointer));
1409 A, Opts.getOption(options::OPT_fno_omit_frame_pointer));
1411 // Don't warn about /Oy- in x86-64 builds (where
1412 // SupportsForcingFramePointer is false). The flag having no effect
1413 // there is a compiler-internal optimization, and people shouldn't have
1414 // to special-case their build files for x86-64 clang-cl.
1423 static void TranslateDArg(Arg *A, llvm::opt::DerivedArgList &DAL,
1424 const OptTable &Opts) {
1425 assert(A->getOption().matches(options::OPT_D));
1427 StringRef Val = A->getValue();
1428 size_t Hash = Val.find('#');
1429 if (Hash == StringRef::npos || Hash > Val.find('=')) {
1434 std::string NewVal = Val;
1436 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_D), NewVal);
1439 llvm::opt::DerivedArgList *
1440 MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
1441 StringRef BoundArch, Action::OffloadKind) const {
1442 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
1443 const OptTable &Opts = getDriver().getOpts();
1445 // /Oy and /Oy- don't have an effect on X86-64
1446 bool SupportsForcingFramePointer = getArch() != llvm::Triple::x86_64;
1448 // The -O[12xd] flag actually expands to several flags. We must desugar the
1449 // flags so that options embedded can be negated. For example, the '-O2' flag
1450 // enables '-Oy'. Expanding '-O2' into its constituent flags allows us to
1451 // correctly handle '-O2 -Oy-' where the trailing '-Oy-' disables a single
1454 // Note that this expansion logic only applies to the *last* of '[12xd]'.
1456 // First step is to search for the character we'd like to expand.
1457 const char *ExpandChar = nullptr;
1458 for (Arg *A : Args.filtered(options::OPT__SLASH_O)) {
1459 StringRef OptStr = A->getValue();
1460 for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
1461 char OptChar = OptStr[I];
1462 char PrevChar = I > 0 ? OptStr[I - 1] : '0';
1463 if (PrevChar == 'b') {
1464 // OptChar does not expand; it's an argument to the previous char.
1467 if (OptChar == '1' || OptChar == '2' || OptChar == 'x' || OptChar == 'd')
1468 ExpandChar = OptStr.data() + I;
1472 for (Arg *A : Args) {
1473 if (A->getOption().matches(options::OPT__SLASH_O)) {
1474 // The -O flag actually takes an amalgam of other options. For example,
1475 // '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'.
1476 TranslateOptArg(A, *DAL, SupportsForcingFramePointer, ExpandChar, Opts);
1477 } else if (A->getOption().matches(options::OPT_D)) {
1478 // Translate -Dfoo#bar into -Dfoo=bar.
1479 TranslateDArg(A, *DAL, Opts);