1//===--- ToolChains.cpp - ToolChain Implementations -----------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "ToolChains.h"
11#include "clang/Basic/CharInfo.h"
12#include "clang/Basic/Version.h"
13#include "clang/Driver/Compilation.h"
14#include "clang/Driver/Driver.h"
15#include "clang/Driver/DriverDiagnostic.h"
16#include "clang/Driver/Options.h"
17#include "llvm/Config/llvm-config.h"
18#include "llvm/Option/Arg.h"
19#include "llvm/Option/ArgList.h"
20#include "llvm/Support/ErrorHandling.h"
21#include "llvm/Support/Path.h"
22
23// Include the necessary headers to interface with the Windows registry and
24// environment.
25#if defined(LLVM_ON_WIN32)
26#define USE_WIN32
27#endif
28
29#ifdef USE_WIN32
30  #define WIN32_LEAN_AND_MEAN
31  #define NOGDI
32  #define NOMINMAX
33  #include <windows.h>
34#endif
35
36using namespace clang::driver;
37using namespace clang::driver::toolchains;
38using namespace clang;
39using namespace llvm::opt;
40
41Windows::Windows(const Driver &D, const llvm::Triple& Triple,
42                 const ArgList &Args)
43  : ToolChain(D, Triple, Args) {
44}
45
46Tool *Windows::buildLinker() const {
47  return new tools::visualstudio::Link(*this);
48}
49
50Tool *Windows::buildAssembler() const {
51  if (getTriple().isOSBinFormatMachO())
52    return new tools::darwin::Assemble(*this);
53  getDriver().Diag(clang::diag::err_no_external_assembler);
54  return nullptr;
55}
56
57bool Windows::IsIntegratedAssemblerDefault() const {
58  return true;
59}
60
61bool Windows::IsUnwindTablesDefault() const {
62  // FIXME: LLVM's lowering of Win64 data is broken right now.  MSVC's linker
63  // says that our object files provide invalid .pdata contributions.  Until
64  // that is fixed, don't ask for unwind tables.
65  return false;
66  //return getArch() == llvm::Triple::x86_64;
67}
68
69bool Windows::isPICDefault() const {
70  return getArch() == llvm::Triple::x86_64;
71}
72
73bool Windows::isPIEDefault() const {
74  return false;
75}
76
77bool Windows::isPICDefaultForced() const {
78  return getArch() == llvm::Triple::x86_64;
79}
80
81/// \brief Read registry string.
82/// This also supports a means to look for high-versioned keys by use
83/// of a $VERSION placeholder in the key path.
84/// $VERSION in the key path is a placeholder for the version number,
85/// causing the highest value path to be searched for and used.
86/// I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
87/// There can be additional characters in the component.  Only the numberic
88/// characters are compared.
89static bool getSystemRegistryString(const char *keyPath, const char *valueName,
90                                    char *value, size_t maxLength) {
91#ifndef USE_WIN32
92  return false;
93#else
94  HKEY hRootKey = NULL;
95  HKEY hKey = NULL;
96  const char* subKey = NULL;
97  DWORD valueType;
98  DWORD valueSize = maxLength - 1;
99  long lResult;
100  bool returnValue = false;
101
102  if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) {
103    hRootKey = HKEY_CLASSES_ROOT;
104    subKey = keyPath + 18;
105  } else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) {
106    hRootKey = HKEY_USERS;
107    subKey = keyPath + 11;
108  } else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) {
109    hRootKey = HKEY_LOCAL_MACHINE;
110    subKey = keyPath + 19;
111  } else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) {
112    hRootKey = HKEY_CURRENT_USER;
113    subKey = keyPath + 18;
114  } else {
115    return false;
116  }
117
118  const char *placeHolder = strstr(subKey, "$VERSION");
119  char bestName[256];
120  bestName[0] = '\0';
121  // If we have a $VERSION placeholder, do the highest-version search.
122  if (placeHolder) {
123    const char *keyEnd = placeHolder - 1;
124    const char *nextKey = placeHolder;
125    // Find end of previous key.
126    while ((keyEnd > subKey) && (*keyEnd != '\\'))
127      keyEnd--;
128    // Find end of key containing $VERSION.
129    while (*nextKey && (*nextKey != '\\'))
130      nextKey++;
131    size_t partialKeyLength = keyEnd - subKey;
132    char partialKey[256];
133    if (partialKeyLength > sizeof(partialKey))
134      partialKeyLength = sizeof(partialKey);
135    strncpy(partialKey, subKey, partialKeyLength);
136    partialKey[partialKeyLength] = '\0';
137    HKEY hTopKey = NULL;
138    lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY,
139                           &hTopKey);
140    if (lResult == ERROR_SUCCESS) {
141      char keyName[256];
142      int bestIndex = -1;
143      double bestValue = 0.0;
144      DWORD index, size = sizeof(keyName) - 1;
145      for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL,
146          NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
147        const char *sp = keyName;
148        while (*sp && !isDigit(*sp))
149          sp++;
150        if (!*sp)
151          continue;
152        const char *ep = sp + 1;
153        while (*ep && (isDigit(*ep) || (*ep == '.')))
154          ep++;
155        char numBuf[32];
156        strncpy(numBuf, sp, sizeof(numBuf) - 1);
157        numBuf[sizeof(numBuf) - 1] = '\0';
158        double dvalue = strtod(numBuf, NULL);
159        if (dvalue > bestValue) {
160          // Test that InstallDir is indeed there before keeping this index.
161          // Open the chosen key path remainder.
162          strcpy(bestName, keyName);
163          // Append rest of key.
164          strncat(bestName, nextKey, sizeof(bestName) - 1);
165          bestName[sizeof(bestName) - 1] = '\0';
166          lResult = RegOpenKeyEx(hTopKey, bestName, 0,
167                                 KEY_READ | KEY_WOW64_32KEY, &hKey);
168          if (lResult == ERROR_SUCCESS) {
169            lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
170              (LPBYTE)value, &valueSize);
171            if (lResult == ERROR_SUCCESS) {
172              bestIndex = (int)index;
173              bestValue = dvalue;
174              returnValue = true;
175            }
176            RegCloseKey(hKey);
177          }
178        }
179        size = sizeof(keyName) - 1;
180      }
181      RegCloseKey(hTopKey);
182    }
183  } else {
184    lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ | KEY_WOW64_32KEY,
185                           &hKey);
186    if (lResult == ERROR_SUCCESS) {
187      lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
188        (LPBYTE)value, &valueSize);
189      if (lResult == ERROR_SUCCESS)
190        returnValue = true;
191      RegCloseKey(hKey);
192    }
193  }
194  return returnValue;
195#endif // USE_WIN32
196}
197
198/// \brief Get Windows SDK installation directory.
199static bool getWindowsSDKDir(std::string &path) {
200  char windowsSDKInstallDir[256];
201  // Try the Windows registry.
202  bool hasSDKDir = getSystemRegistryString(
203   "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
204                                           "InstallationFolder",
205                                           windowsSDKInstallDir,
206                                           sizeof(windowsSDKInstallDir) - 1);
207    // If we have both vc80 and vc90, pick version we were compiled with.
208  if (hasSDKDir && windowsSDKInstallDir[0]) {
209    path = windowsSDKInstallDir;
210    return true;
211  }
212  return false;
213}
214
215// Get Visual Studio installation directory.
216static bool getVisualStudioDir(std::string &path) {
217  // First check the environment variables that vsvars32.bat sets.
218  const char* vcinstalldir = getenv("VCINSTALLDIR");
219  if (vcinstalldir) {
220    char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC"));
221    if (p)
222      *p = '\0';
223    path = vcinstalldir;
224    return true;
225  }
226
227  char vsIDEInstallDir[256];
228  char vsExpressIDEInstallDir[256];
229  // Then try the windows registry.
230  bool hasVCDir = getSystemRegistryString(
231    "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
232    "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1);
233  bool hasVCExpressDir = getSystemRegistryString(
234    "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\$VERSION",
235    "InstallDir", vsExpressIDEInstallDir, sizeof(vsExpressIDEInstallDir) - 1);
236    // If we have both vc80 and vc90, pick version we were compiled with.
237  if (hasVCDir && vsIDEInstallDir[0]) {
238    char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE");
239    if (p)
240      *p = '\0';
241    path = vsIDEInstallDir;
242    return true;
243  }
244
245  if (hasVCExpressDir && vsExpressIDEInstallDir[0]) {
246    char *p = (char*)strstr(vsExpressIDEInstallDir, "\\Common7\\IDE");
247    if (p)
248      *p = '\0';
249    path = vsExpressIDEInstallDir;
250    return true;
251  }
252
253  // Try the environment.
254  const char *vs100comntools = getenv("VS100COMNTOOLS");
255  const char *vs90comntools = getenv("VS90COMNTOOLS");
256  const char *vs80comntools = getenv("VS80COMNTOOLS");
257
258  const char *vscomntools = nullptr;
259
260  // Find any version we can
261  if (vs100comntools)
262    vscomntools = vs100comntools;
263  else if (vs90comntools)
264    vscomntools = vs90comntools;
265  else if (vs80comntools)
266    vscomntools = vs80comntools;
267
268  if (vscomntools && *vscomntools) {
269    const char *p = strstr(vscomntools, "\\Common7\\Tools");
270    path = p ? std::string(vscomntools, p) : vscomntools;
271    return true;
272  }
273  return false;
274}
275
276void Windows::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
277                                        ArgStringList &CC1Args) const {
278  if (DriverArgs.hasArg(options::OPT_nostdinc))
279    return;
280
281  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
282    SmallString<128> P(getDriver().ResourceDir);
283    llvm::sys::path::append(P, "include");
284    addSystemInclude(DriverArgs, CC1Args, P.str());
285  }
286
287  if (DriverArgs.hasArg(options::OPT_nostdlibinc))
288    return;
289
290  // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat.
291  if (const char *cl_include_dir = getenv("INCLUDE")) {
292    SmallVector<StringRef, 8> Dirs;
293    StringRef(cl_include_dir)
294        .split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
295    for (StringRef Dir : Dirs)
296      addSystemInclude(DriverArgs, CC1Args, Dir);
297    if (!Dirs.empty())
298      return;
299  }
300
301  std::string VSDir;
302  std::string WindowsSDKDir;
303
304  // When built with access to the proper Windows APIs, try to actually find
305  // the correct include paths first.
306  if (getVisualStudioDir(VSDir)) {
307    SmallString<128> P;
308    P = VSDir;
309    llvm::sys::path::append(P, "VC\\include");
310    addSystemInclude(DriverArgs, CC1Args, P.str());
311    if (getWindowsSDKDir(WindowsSDKDir)) {
312      P = WindowsSDKDir;
313      llvm::sys::path::append(P, "include");
314      addSystemInclude(DriverArgs, CC1Args, P.str());
315    } else {
316      P = VSDir;
317      llvm::sys::path::append(P, "VC\\PlatformSDK\\Include");
318      addSystemInclude(DriverArgs, CC1Args, P.str());
319    }
320    return;
321  }
322
323  // As a fallback, select default install paths.
324  // FIXME: Don't guess drives and paths like this on Windows.
325  const StringRef Paths[] = {
326    "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
327    "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
328    "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
329    "C:/Program Files/Microsoft Visual Studio 8/VC/include",
330    "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
331  };
332  addSystemIncludes(DriverArgs, CC1Args, Paths);
333}
334
335void Windows::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
336                                           ArgStringList &CC1Args) const {
337  // FIXME: There should probably be logic here to find libc++ on Windows.
338}
339