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