MSVCToolChain.cpp revision a4de17562d13d7a8188108243c4cfbd52f33229a
19859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org//===--- ToolChains.cpp - ToolChain Implementations -----------------------===//
29859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org//
39859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org//                     The LLVM Compiler Infrastructure
49859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org//
59859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org// This file is distributed under the University of Illinois Open Source
69859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org// License. See LICENSE.TXT for details.
79859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org//
89859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org//===----------------------------------------------------------------------===//
99859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org
109859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#include "ToolChains.h"
119859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#include "Tools.h"
129859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#include "clang/Basic/CharInfo.h"
139859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#include "clang/Basic/Version.h"
149859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#include "clang/Driver/Compilation.h"
159859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#include "clang/Driver/Driver.h"
169859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#include "clang/Driver/DriverDiagnostic.h"
179859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#include "clang/Driver/Options.h"
189859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#include "llvm/ADT/StringExtras.h"
199859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#include "llvm/Config/llvm-config.h"
209859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#include "llvm/Option/Arg.h"
219859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#include "llvm/Option/ArgList.h"
229859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#include "llvm/Support/ErrorHandling.h"
239859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#include "llvm/Support/FileSystem.h"
249859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#include "llvm/Support/Process.h"
259859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#include <cstdio>
269859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org
279859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org// Include the necessary headers to interface with the Windows registry and
289859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org// environment.
299859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#if defined(LLVM_ON_WIN32)
309859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#define USE_WIN32
319859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#endif
329859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org
339859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#ifdef USE_WIN32
349859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org  #define WIN32_LEAN_AND_MEAN
359859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org  #define NOGDI
369859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org  #ifndef NOMINMAX
379859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org    #define NOMINMAX
389859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org  #endif
399859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org  #include <windows.h>
409859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#endif
419859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org
429859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.orgusing namespace clang::driver;
439859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.orgusing namespace clang::driver::toolchains;
449859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.orgusing namespace clang;
459859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.orgusing namespace llvm::opt;
469859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org
479859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.orgMSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple& Triple,
489859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org                             const ArgList &Args)
499859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org  : ToolChain(D, Triple, Args) {
509859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org  getProgramPaths().push_back(getDriver().getInstalledDir());
519859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org  if (getDriver().getInstalledDir() != getDriver().Dir)
529859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org    getProgramPaths().push_back(getDriver().Dir);
539859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org}
549859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org
559859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.orgTool *MSVCToolChain::buildLinker() const {
569859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org  return new tools::visualstudio::Linker(*this);
579859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org}
589859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org
599859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.orgTool *MSVCToolChain::buildAssembler() const {
609859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org  if (getTriple().isOSBinFormatMachO())
619859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org    return new tools::darwin::Assembler(*this);
629859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org  getDriver().Diag(clang::diag::err_no_external_assembler);
639859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org  return nullptr;
649859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org}
659859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org
669859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.orgbool MSVCToolChain::IsIntegratedAssemblerDefault() const {
679859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org  return true;
689859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org}
699859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org
709859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.orgbool MSVCToolChain::IsUnwindTablesDefault() const {
719859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org  // Emit unwind tables by default on Win64. All non-x86_32 Windows platforms
729859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org  // such as ARM and PPC actually require unwind tables, but LLVM doesn't know
739859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org  // how to generate them yet.
749859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org  return getArch() == llvm::Triple::x86_64;
759859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org}
769859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org
779859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.orgbool MSVCToolChain::isPICDefault() const {
789859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org  return getArch() == llvm::Triple::x86_64;
799859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org}
809859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org
819859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.orgbool MSVCToolChain::isPIEDefault() const {
829859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org  return false;
839859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org}
849859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org
859859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.orgbool MSVCToolChain::isPICDefaultForced() const {
869859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org  return getArch() == llvm::Triple::x86_64;
879859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org}
889859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org
899859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.org#ifdef USE_WIN32
909859428e71c6041928e6dd741ae3284017e78e81vandebo@chromium.orgstatic bool readFullStringValue(HKEY hkey, const char *valueName,
91                                std::string &value) {
92  // FIXME: We should be using the W versions of the registry functions, but
93  // doing so requires UTF8 / UTF16 conversions similar to how we handle command
94  // line arguments.  The UTF8 conversion functions are not exposed publicly
95  // from LLVM though, so in order to do this we will probably need to create
96  // a registry abstraction in LLVMSupport that is Windows only.
97  DWORD result = 0;
98  DWORD valueSize = 0;
99  DWORD type = 0;
100  // First just query for the required size.
101  result = RegQueryValueEx(hkey, valueName, NULL, &type, NULL, &valueSize);
102  if (result != ERROR_SUCCESS || type != REG_SZ)
103    return false;
104  std::vector<BYTE> buffer(valueSize);
105  result = RegQueryValueEx(hkey, valueName, NULL, NULL, &buffer[0], &valueSize);
106  if (result == ERROR_SUCCESS)
107    value.assign(reinterpret_cast<const char *>(buffer.data()));
108  return result;
109}
110#endif
111
112/// \brief Read registry string.
113/// This also supports a means to look for high-versioned keys by use
114/// of a $VERSION placeholder in the key path.
115/// $VERSION in the key path is a placeholder for the version number,
116/// causing the highest value path to be searched for and used.
117/// I.e. "SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
118/// There can be additional characters in the component.  Only the numeric
119/// characters are compared.  This function only searches HKLM.
120static bool getSystemRegistryString(const char *keyPath, const char *valueName,
121                                    std::string &value, std::string *phValue) {
122#ifndef USE_WIN32
123  return false;
124#else
125  HKEY hRootKey = HKEY_LOCAL_MACHINE;
126  HKEY hKey = NULL;
127  long lResult;
128  bool returnValue = false;
129
130  const char *placeHolder = strstr(keyPath, "$VERSION");
131  std::string bestName;
132  // If we have a $VERSION placeholder, do the highest-version search.
133  if (placeHolder) {
134    const char *keyEnd = placeHolder - 1;
135    const char *nextKey = placeHolder;
136    // Find end of previous key.
137    while ((keyEnd > keyPath) && (*keyEnd != '\\'))
138      keyEnd--;
139    // Find end of key containing $VERSION.
140    while (*nextKey && (*nextKey != '\\'))
141      nextKey++;
142    size_t partialKeyLength = keyEnd - keyPath;
143    char partialKey[256];
144    if (partialKeyLength > sizeof(partialKey))
145      partialKeyLength = sizeof(partialKey);
146    strncpy(partialKey, keyPath, partialKeyLength);
147    partialKey[partialKeyLength] = '\0';
148    HKEY hTopKey = NULL;
149    lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY,
150                           &hTopKey);
151    if (lResult == ERROR_SUCCESS) {
152      char keyName[256];
153      double bestValue = 0.0;
154      DWORD index, size = sizeof(keyName) - 1;
155      for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL,
156          NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
157        const char *sp = keyName;
158        while (*sp && !isDigit(*sp))
159          sp++;
160        if (!*sp)
161          continue;
162        const char *ep = sp + 1;
163        while (*ep && (isDigit(*ep) || (*ep == '.')))
164          ep++;
165        char numBuf[32];
166        strncpy(numBuf, sp, sizeof(numBuf) - 1);
167        numBuf[sizeof(numBuf) - 1] = '\0';
168        double dvalue = strtod(numBuf, NULL);
169        if (dvalue > bestValue) {
170          // Test that InstallDir is indeed there before keeping this index.
171          // Open the chosen key path remainder.
172          bestName = keyName;
173          // Append rest of key.
174          bestName.append(nextKey);
175          lResult = RegOpenKeyEx(hTopKey, bestName.c_str(), 0,
176                                 KEY_READ | KEY_WOW64_32KEY, &hKey);
177          if (lResult == ERROR_SUCCESS) {
178            lResult = readFullStringValue(hKey, valueName, value);
179            if (lResult == ERROR_SUCCESS) {
180              bestValue = dvalue;
181              if (phValue)
182                *phValue = bestName;
183              returnValue = true;
184            }
185            RegCloseKey(hKey);
186          }
187        }
188        size = sizeof(keyName) - 1;
189      }
190      RegCloseKey(hTopKey);
191    }
192  } else {
193    lResult =
194        RegOpenKeyEx(hRootKey, keyPath, 0, KEY_READ | KEY_WOW64_32KEY, &hKey);
195    if (lResult == ERROR_SUCCESS) {
196      lResult = readFullStringValue(hKey, valueName, value);
197      if (lResult == ERROR_SUCCESS)
198        returnValue = true;
199      if (phValue)
200        phValue->clear();
201      RegCloseKey(hKey);
202    }
203  }
204  return returnValue;
205#endif // USE_WIN32
206}
207
208// Convert LLVM's ArchType
209// to the corresponding name of Windows SDK libraries subfolder
210static StringRef getWindowsSDKArch(llvm::Triple::ArchType Arch) {
211  switch (Arch) {
212  case llvm::Triple::x86:
213    return "x86";
214  case llvm::Triple::x86_64:
215    return "x64";
216  case llvm::Triple::arm:
217    return "arm";
218  default:
219    return "";
220  }
221}
222
223// Find the most recent version of Universal CRT or Windows 10 SDK.
224// vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include
225// directory by name and uses the last one of the list.
226// So we compare entry names lexicographically to find the greatest one.
227static bool getWindows10SDKVersion(const std::string &SDKPath,
228                                   std::string &SDKVersion) {
229  SDKVersion.clear();
230
231  std::error_code EC;
232  llvm::SmallString<128> IncludePath(SDKPath);
233  llvm::sys::path::append(IncludePath, "Include");
234  for (llvm::sys::fs::directory_iterator DirIt(IncludePath, EC), DirEnd;
235       DirIt != DirEnd && !EC; DirIt.increment(EC)) {
236    if (!llvm::sys::fs::is_directory(DirIt->path()))
237      continue;
238    StringRef CandidateName = llvm::sys::path::filename(DirIt->path());
239    // If WDK is installed, there could be subfolders like "wdf" in the
240    // "Include" directory.
241    // Allow only directories which names start with "10.".
242    if (!CandidateName.startswith("10."))
243      continue;
244    if (CandidateName > SDKVersion)
245      SDKVersion = CandidateName;
246  }
247
248  return !SDKVersion.empty();
249}
250
251/// \brief Get Windows SDK installation directory.
252bool MSVCToolChain::getWindowsSDKDir(std::string &Path, int &Major,
253                                     std::string &WindowsSDKIncludeVersion,
254                                     std::string &WindowsSDKLibVersion) const {
255  std::string RegistrySDKVersion;
256  // Try the Windows registry.
257  if (!getSystemRegistryString(
258          "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
259          "InstallationFolder", Path, &RegistrySDKVersion))
260    return false;
261  if (Path.empty() || RegistrySDKVersion.empty())
262    return false;
263
264  WindowsSDKIncludeVersion.clear();
265  WindowsSDKLibVersion.clear();
266  Major = 0;
267  std::sscanf(RegistrySDKVersion.c_str(), "v%d.", &Major);
268  if (Major <= 7)
269    return true;
270  if (Major == 8) {
271    // Windows SDK 8.x installs libraries in a folder whose names depend on the
272    // version of the OS you're targeting.  By default choose the newest, which
273    // usually corresponds to the version of the OS you've installed the SDK on.
274    const char *Tests[] = {"winv6.3", "win8", "win7"};
275    for (const char *Test : Tests) {
276      llvm::SmallString<128> TestPath(Path);
277      llvm::sys::path::append(TestPath, "Lib", Test);
278      if (llvm::sys::fs::exists(TestPath.c_str())) {
279        WindowsSDKLibVersion = Test;
280        break;
281      }
282    }
283    return !WindowsSDKLibVersion.empty();
284  }
285  if (Major == 10) {
286    if (!getWindows10SDKVersion(Path, WindowsSDKIncludeVersion))
287      return false;
288    WindowsSDKLibVersion = WindowsSDKIncludeVersion;
289    return true;
290  }
291  // Unsupported SDK version
292  return false;
293}
294
295// Gets the library path required to link against the Windows SDK.
296bool MSVCToolChain::getWindowsSDKLibraryPath(std::string &path) const {
297  std::string sdkPath;
298  int sdkMajor = 0;
299  std::string windowsSDKIncludeVersion;
300  std::string windowsSDKLibVersion;
301
302  path.clear();
303  if (!getWindowsSDKDir(sdkPath, sdkMajor, windowsSDKIncludeVersion,
304                        windowsSDKLibVersion))
305    return false;
306
307  llvm::SmallString<128> libPath(sdkPath);
308  llvm::sys::path::append(libPath, "Lib");
309  if (sdkMajor <= 7) {
310    switch (getArch()) {
311    // In Windows SDK 7.x, x86 libraries are directly in the Lib folder.
312    case llvm::Triple::x86:
313      break;
314    case llvm::Triple::x86_64:
315      llvm::sys::path::append(libPath, "x64");
316      break;
317    case llvm::Triple::arm:
318      // It is not necessary to link against Windows SDK 7.x when targeting ARM.
319      return false;
320    default:
321      return false;
322    }
323  } else {
324    const StringRef archName = getWindowsSDKArch(getArch());
325    if (archName.empty())
326      return false;
327    llvm::sys::path::append(libPath, windowsSDKLibVersion, "um", archName);
328  }
329
330  path = libPath.str();
331  return true;
332}
333
334// Check if the Include path of a specified version of Visual Studio contains
335// specific header files. If not, they are probably shipped with Universal CRT.
336bool clang::driver::toolchains::MSVCToolChain::useUniversalCRT(
337    std::string &VisualStudioDir) const {
338  llvm::SmallString<128> TestPath(VisualStudioDir);
339  llvm::sys::path::append(TestPath, "VC\\include\\stdlib.h");
340
341  return !llvm::sys::fs::exists(TestPath);
342}
343
344bool MSVCToolChain::getUniversalCRTSdkDir(std::string &Path,
345                                          std::string &UCRTVersion) const {
346  // vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry
347  // for the specific key "KitsRoot10". So do we.
348  if (!getSystemRegistryString(
349          "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10",
350          Path, nullptr))
351    return false;
352
353  return getWindows10SDKVersion(Path, UCRTVersion);
354}
355
356bool MSVCToolChain::getUniversalCRTLibraryPath(std::string &Path) const {
357  std::string UniversalCRTSdkPath;
358  std::string UCRTVersion;
359
360  Path.clear();
361  if (!getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion))
362    return false;
363
364  StringRef ArchName = getWindowsSDKArch(getArch());
365  if (ArchName.empty())
366    return false;
367
368  llvm::SmallString<128> LibPath(UniversalCRTSdkPath);
369  llvm::sys::path::append(LibPath, "Lib", UCRTVersion, "ucrt", ArchName);
370
371  Path = LibPath.str();
372  return true;
373}
374
375// Get the location to use for Visual Studio binaries.  The location priority
376// is: %VCINSTALLDIR% > %PATH% > newest copy of Visual Studio installed on
377// system (as reported by the registry).
378bool MSVCToolChain::getVisualStudioBinariesFolder(const char *clangProgramPath,
379                                                  std::string &path) const {
380  path.clear();
381
382  SmallString<128> BinDir;
383
384  // First check the environment variables that vsvars32.bat sets.
385  llvm::Optional<std::string> VcInstallDir =
386      llvm::sys::Process::GetEnv("VCINSTALLDIR");
387  if (VcInstallDir.hasValue()) {
388    BinDir = VcInstallDir.getValue();
389    llvm::sys::path::append(BinDir, "bin");
390  } else {
391    // Next walk the PATH, trying to find a cl.exe in the path.  If we find one,
392    // use that.  However, make sure it's not clang's cl.exe.
393    llvm::Optional<std::string> OptPath = llvm::sys::Process::GetEnv("PATH");
394    if (OptPath.hasValue()) {
395      const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
396      SmallVector<StringRef, 8> PathSegments;
397      llvm::SplitString(OptPath.getValue(), PathSegments, EnvPathSeparatorStr);
398
399      for (StringRef PathSegment : PathSegments) {
400        if (PathSegment.empty())
401          continue;
402
403        SmallString<128> FilePath(PathSegment);
404        llvm::sys::path::append(FilePath, "cl.exe");
405        if (llvm::sys::fs::can_execute(FilePath.c_str()) &&
406            !llvm::sys::fs::equivalent(FilePath.c_str(), clangProgramPath)) {
407          // If we found it on the PATH, use it exactly as is with no
408          // modifications.
409          path = PathSegment;
410          return true;
411        }
412      }
413    }
414
415    std::string installDir;
416    // With no VCINSTALLDIR and nothing on the PATH, if we can't find it in the
417    // registry then we have no choice but to fail.
418    if (!getVisualStudioInstallDir(installDir))
419      return false;
420
421    // Regardless of what binary we're ultimately trying to find, we make sure
422    // that this is a Visual Studio directory by checking for cl.exe.  We use
423    // cl.exe instead of other binaries like link.exe because programs such as
424    // GnuWin32 also have a utility called link.exe, so cl.exe is the least
425    // ambiguous.
426    BinDir = installDir;
427    llvm::sys::path::append(BinDir, "VC", "bin");
428    SmallString<128> ClPath(BinDir);
429    llvm::sys::path::append(ClPath, "cl.exe");
430
431    if (!llvm::sys::fs::can_execute(ClPath.c_str()))
432      return false;
433  }
434
435  if (BinDir.empty())
436    return false;
437
438  switch (getArch()) {
439  case llvm::Triple::x86:
440    break;
441  case llvm::Triple::x86_64:
442    llvm::sys::path::append(BinDir, "amd64");
443    break;
444  case llvm::Triple::arm:
445    llvm::sys::path::append(BinDir, "arm");
446    break;
447  default:
448    // Whatever this is, Visual Studio doesn't have a toolchain for it.
449    return false;
450  }
451  path = BinDir.str();
452  return true;
453}
454
455// Get Visual Studio installation directory.
456bool MSVCToolChain::getVisualStudioInstallDir(std::string &path) const {
457  // First check the environment variables that vsvars32.bat sets.
458  const char *vcinstalldir = getenv("VCINSTALLDIR");
459  if (vcinstalldir) {
460    path = vcinstalldir;
461    path = path.substr(0, path.find("\\VC"));
462    return true;
463  }
464
465  std::string vsIDEInstallDir;
466  std::string vsExpressIDEInstallDir;
467  // Then try the windows registry.
468  bool hasVCDir =
469      getSystemRegistryString("SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
470                              "InstallDir", vsIDEInstallDir, nullptr);
471  if (hasVCDir && !vsIDEInstallDir.empty()) {
472    path = vsIDEInstallDir.substr(0, vsIDEInstallDir.find("\\Common7\\IDE"));
473    return true;
474  }
475
476  bool hasVCExpressDir =
477      getSystemRegistryString("SOFTWARE\\Microsoft\\VCExpress\\$VERSION",
478                              "InstallDir", vsExpressIDEInstallDir, nullptr);
479  if (hasVCExpressDir && !vsExpressIDEInstallDir.empty()) {
480    path = vsExpressIDEInstallDir.substr(
481        0, vsIDEInstallDir.find("\\Common7\\IDE"));
482    return true;
483  }
484
485  // Try the environment.
486  const char *vs120comntools = getenv("VS120COMNTOOLS");
487  const char *vs100comntools = getenv("VS100COMNTOOLS");
488  const char *vs90comntools = getenv("VS90COMNTOOLS");
489  const char *vs80comntools = getenv("VS80COMNTOOLS");
490
491  const char *vscomntools = nullptr;
492
493  // Find any version we can
494  if (vs120comntools)
495    vscomntools = vs120comntools;
496  else if (vs100comntools)
497    vscomntools = vs100comntools;
498  else if (vs90comntools)
499    vscomntools = vs90comntools;
500  else if (vs80comntools)
501    vscomntools = vs80comntools;
502
503  if (vscomntools && *vscomntools) {
504    const char *p = strstr(vscomntools, "\\Common7\\Tools");
505    path = p ? std::string(vscomntools, p) : vscomntools;
506    return true;
507  }
508  return false;
509}
510
511void MSVCToolChain::AddSystemIncludeWithSubfolder(
512    const ArgList &DriverArgs, ArgStringList &CC1Args,
513    const std::string &folder, const Twine &subfolder1, const Twine &subfolder2,
514    const Twine &subfolder3) const {
515  llvm::SmallString<128> path(folder);
516  llvm::sys::path::append(path, subfolder1, subfolder2, subfolder3);
517  addSystemInclude(DriverArgs, CC1Args, path);
518}
519
520void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
521                                              ArgStringList &CC1Args) const {
522  if (DriverArgs.hasArg(options::OPT_nostdinc))
523    return;
524
525  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
526    AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, getDriver().ResourceDir,
527                                  "include");
528  }
529
530  if (DriverArgs.hasArg(options::OPT_nostdlibinc))
531    return;
532
533  // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat.
534  if (const char *cl_include_dir = getenv("INCLUDE")) {
535    SmallVector<StringRef, 8> Dirs;
536    StringRef(cl_include_dir)
537        .split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
538    for (StringRef Dir : Dirs)
539      addSystemInclude(DriverArgs, CC1Args, Dir);
540    if (!Dirs.empty())
541      return;
542  }
543
544  std::string VSDir;
545
546  // When built with access to the proper Windows APIs, try to actually find
547  // the correct include paths first.
548  if (getVisualStudioInstallDir(VSDir)) {
549    AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, VSDir, "VC\\include");
550
551    if (useUniversalCRT(VSDir)) {
552      std::string UniversalCRTSdkPath;
553      std::string UCRTVersion;
554      if (getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion)) {
555        AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath,
556                                      "Include", UCRTVersion, "ucrt");
557      }
558    }
559
560    std::string WindowsSDKDir;
561    int major;
562    std::string windowsSDKIncludeVersion;
563    std::string windowsSDKLibVersion;
564    if (getWindowsSDKDir(WindowsSDKDir, major, windowsSDKIncludeVersion,
565                         windowsSDKLibVersion)) {
566      if (major >= 8) {
567        // Note: windowsSDKIncludeVersion is empty for SDKs prior to v10.
568        // Anyway, llvm::sys::path::append is able to manage it.
569        AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
570                                      "include", windowsSDKIncludeVersion,
571                                      "shared");
572        AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
573                                      "include", windowsSDKIncludeVersion,
574                                      "um");
575        AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
576                                      "include", windowsSDKIncludeVersion,
577                                      "winrt");
578      } else {
579        AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
580                                      "include");
581      }
582    } else {
583      addSystemInclude(DriverArgs, CC1Args, VSDir);
584    }
585    return;
586  }
587
588  // As a fallback, select default install paths.
589  // FIXME: Don't guess drives and paths like this on Windows.
590  const StringRef Paths[] = {
591    "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
592    "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
593    "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
594    "C:/Program Files/Microsoft Visual Studio 8/VC/include",
595    "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
596  };
597  addSystemIncludes(DriverArgs, CC1Args, Paths);
598}
599
600void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
601                                                 ArgStringList &CC1Args) const {
602  // FIXME: There should probably be logic here to find libc++ on Windows.
603}
604
605std::string
606MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
607                                           types::ID InputType) const {
608  std::string TripleStr =
609      ToolChain::ComputeEffectiveClangTriple(Args, InputType);
610  llvm::Triple Triple(TripleStr);
611  VersionTuple MSVT =
612      tools::visualstudio::getMSVCVersion(/*D=*/nullptr, Triple, Args,
613                                          /*IsWindowsMSVC=*/true);
614  if (MSVT.empty())
615    return TripleStr;
616
617  MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().getValueOr(0),
618                      MSVT.getSubminor().getValueOr(0));
619
620  if (Triple.getEnvironment() == llvm::Triple::MSVC) {
621    StringRef ObjFmt = Triple.getEnvironmentName().split('-').second;
622    if (ObjFmt.empty())
623      Triple.setEnvironmentName((Twine("msvc") + MSVT.getAsString()).str());
624    else
625      Triple.setEnvironmentName(
626          (Twine("msvc") + MSVT.getAsString() + Twine('-') + ObjFmt).str());
627  }
628  return Triple.getTriple();
629}
630
631SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
632  SanitizerMask Res = ToolChain::getSupportedSanitizers();
633  Res |= SanitizerKind::Address;
634  return Res;
635}
636
637llvm::opt::DerivedArgList *
638MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
639                             const char *BoundArch) const {
640  DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
641  const OptTable &Opts = getDriver().getOpts();
642
643  // /Oy and /Oy- only has an effect under X86-32.
644  bool SupportsForcingFramePointer = getArch() == llvm::Triple::x86;
645
646  // The -O[12xd] flag actually expands to several flags.  We must desugar the
647  // flags so that options embedded can be negated.  For example, the '-O2' flag
648  // enables '-Oy'.  Expanding '-O2' into its constituent flags allows us to
649  // correctly handle '-O2 -Oy-' where the trailing '-Oy-' disables a single
650  // aspect of '-O2'.
651  //
652  // Note that this expansion logic only applies to the *last* of '[12xd]'.
653
654  // First step is to search for the character we'd like to expand.
655  const char *ExpandChar = nullptr;
656  for (Arg *A : Args) {
657    if (!A->getOption().matches(options::OPT__SLASH_O))
658      continue;
659    StringRef OptStr = A->getValue();
660    for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
661      const char &OptChar = *(OptStr.data() + I);
662      if (OptChar == '1' || OptChar == '2' || OptChar == 'x' || OptChar == 'd')
663        ExpandChar = OptStr.data() + I;
664    }
665  }
666
667  // The -O flag actually takes an amalgam of other options.  For example,
668  // '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'.
669  for (Arg *A : Args) {
670    if (!A->getOption().matches(options::OPT__SLASH_O)) {
671      DAL->append(A);
672      continue;
673    }
674
675    StringRef OptStr = A->getValue();
676    for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
677      const char &OptChar = *(OptStr.data() + I);
678      switch (OptChar) {
679      default:
680        break;
681      case '1':
682      case '2':
683      case 'x':
684      case 'd':
685        if (&OptChar == ExpandChar) {
686          if (OptChar == 'd') {
687            DAL->AddFlagArg(A, Opts.getOption(options::OPT_O0));
688          } else {
689            if (OptChar == '1') {
690              DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
691            } else if (OptChar == '2' || OptChar == 'x') {
692              DAL->AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
693              DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
694            }
695            if (SupportsForcingFramePointer)
696              DAL->AddFlagArg(A,
697                              Opts.getOption(options::OPT_fomit_frame_pointer));
698            if (OptChar == '1' || OptChar == '2')
699              DAL->AddFlagArg(A,
700                              Opts.getOption(options::OPT_ffunction_sections));
701          }
702        }
703        break;
704      case 'b':
705        if (I + 1 != E && isdigit(OptStr[I + 1]))
706          ++I;
707        break;
708      case 'g':
709        break;
710      case 'i':
711        if (I + 1 != E && OptStr[I + 1] == '-') {
712          ++I;
713          DAL->AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin));
714        } else {
715          DAL->AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
716        }
717        break;
718      case 's':
719        DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
720        break;
721      case 't':
722        DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
723        break;
724      case 'y': {
725        bool OmitFramePointer = true;
726        if (I + 1 != E && OptStr[I + 1] == '-') {
727          OmitFramePointer = false;
728          ++I;
729        }
730        if (SupportsForcingFramePointer) {
731          if (OmitFramePointer)
732            DAL->AddFlagArg(A,
733                            Opts.getOption(options::OPT_fomit_frame_pointer));
734          else
735            DAL->AddFlagArg(
736                A, Opts.getOption(options::OPT_fno_omit_frame_pointer));
737        }
738        break;
739      }
740      }
741    }
742  }
743  return DAL;
744}
745