1234287Sdim//===--- ToolChains.cpp - ToolChain Implementations -----------------------===//
2234287Sdim//
3234287Sdim//                     The LLVM Compiler Infrastructure
4234287Sdim//
5234287Sdim// This file is distributed under the University of Illinois Open Source
6234287Sdim// License. See LICENSE.TXT for details.
7234287Sdim//
8234287Sdim//===----------------------------------------------------------------------===//
9234287Sdim
10234287Sdim#include "ToolChains.h"
11249423Sdim#include "clang/Basic/CharInfo.h"
12249423Sdim#include "clang/Basic/Version.h"
13234287Sdim#include "clang/Driver/Arg.h"
14234287Sdim#include "clang/Driver/ArgList.h"
15234287Sdim#include "clang/Driver/Compilation.h"
16234287Sdim#include "clang/Driver/Driver.h"
17249423Sdim#include "clang/Driver/DriverDiagnostic.h"
18234287Sdim#include "clang/Driver/Options.h"
19234287Sdim#include "llvm/Support/ErrorHandling.h"
20234287Sdim#include "llvm/Support/Path.h"
21234287Sdim
22234287Sdim// Include the necessary headers to interface with the Windows registry and
23234287Sdim// environment.
24234287Sdim#ifdef _MSC_VER
25234287Sdim  #define WIN32_LEAN_AND_MEAN
26234287Sdim  #define NOGDI
27234287Sdim  #define NOMINMAX
28234287Sdim  #include <Windows.h>
29234287Sdim#endif
30234287Sdim
31234287Sdimusing namespace clang::driver;
32234287Sdimusing namespace clang::driver::toolchains;
33234287Sdimusing namespace clang;
34234287Sdim
35249423SdimWindows::Windows(const Driver &D, const llvm::Triple& Triple,
36249423Sdim                 const ArgList &Args)
37249423Sdim  : ToolChain(D, Triple, Args) {
38234287Sdim}
39234287Sdim
40249423SdimTool *Windows::buildLinker() const {
41249423Sdim  return new tools::visualstudio::Link(*this);
42249423Sdim}
43234287Sdim
44249423SdimTool *Windows::buildAssembler() const {
45249423Sdim  if (getTriple().getEnvironment() == llvm::Triple::MachO)
46249423Sdim    return new tools::darwin::Assemble(*this);
47249423Sdim  getDriver().Diag(clang::diag::err_no_external_windows_assembler);
48249423Sdim  return NULL;
49234287Sdim}
50234287Sdim
51234287Sdimbool Windows::IsIntegratedAssemblerDefault() const {
52234287Sdim  return true;
53234287Sdim}
54234287Sdim
55234287Sdimbool Windows::IsUnwindTablesDefault() const {
56243830Sdim  return getArch() == llvm::Triple::x86_64;
57234287Sdim}
58234287Sdim
59243830Sdimbool Windows::isPICDefault() const {
60243830Sdim  return getArch() == llvm::Triple::x86_64;
61234287Sdim}
62234287Sdim
63251662Sdimbool Windows::isPIEDefault() const {
64251662Sdim  return false;
65251662Sdim}
66251662Sdim
67243830Sdimbool Windows::isPICDefaultForced() const {
68243830Sdim  return getArch() == llvm::Triple::x86_64;
69234287Sdim}
70234287Sdim
71234287Sdim// FIXME: This probably should goto to some platform utils place.
72234287Sdim#ifdef _MSC_VER
73234287Sdim
74234287Sdim/// \brief Read registry string.
75234287Sdim/// This also supports a means to look for high-versioned keys by use
76234287Sdim/// of a $VERSION placeholder in the key path.
77234287Sdim/// $VERSION in the key path is a placeholder for the version number,
78234287Sdim/// causing the highest value path to be searched for and used.
79234287Sdim/// I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
80234287Sdim/// There can be additional characters in the component.  Only the numberic
81234287Sdim/// characters are compared.
82234287Sdimstatic bool getSystemRegistryString(const char *keyPath, const char *valueName,
83234287Sdim                                    char *value, size_t maxLength) {
84234287Sdim  HKEY hRootKey = NULL;
85234287Sdim  HKEY hKey = NULL;
86234287Sdim  const char* subKey = NULL;
87234287Sdim  DWORD valueType;
88234287Sdim  DWORD valueSize = maxLength - 1;
89234287Sdim  long lResult;
90234287Sdim  bool returnValue = false;
91234287Sdim
92234287Sdim  if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) {
93234287Sdim    hRootKey = HKEY_CLASSES_ROOT;
94234287Sdim    subKey = keyPath + 18;
95234287Sdim  } else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) {
96234287Sdim    hRootKey = HKEY_USERS;
97234287Sdim    subKey = keyPath + 11;
98234287Sdim  } else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) {
99234287Sdim    hRootKey = HKEY_LOCAL_MACHINE;
100234287Sdim    subKey = keyPath + 19;
101234287Sdim  } else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) {
102234287Sdim    hRootKey = HKEY_CURRENT_USER;
103234287Sdim    subKey = keyPath + 18;
104234287Sdim  } else {
105234287Sdim    return false;
106234287Sdim  }
107234287Sdim
108234287Sdim  const char *placeHolder = strstr(subKey, "$VERSION");
109234287Sdim  char bestName[256];
110234287Sdim  bestName[0] = '\0';
111234287Sdim  // If we have a $VERSION placeholder, do the highest-version search.
112234287Sdim  if (placeHolder) {
113234287Sdim    const char *keyEnd = placeHolder - 1;
114234287Sdim    const char *nextKey = placeHolder;
115234287Sdim    // Find end of previous key.
116234287Sdim    while ((keyEnd > subKey) && (*keyEnd != '\\'))
117234287Sdim      keyEnd--;
118234287Sdim    // Find end of key containing $VERSION.
119234287Sdim    while (*nextKey && (*nextKey != '\\'))
120234287Sdim      nextKey++;
121234287Sdim    size_t partialKeyLength = keyEnd - subKey;
122234287Sdim    char partialKey[256];
123234287Sdim    if (partialKeyLength > sizeof(partialKey))
124234287Sdim      partialKeyLength = sizeof(partialKey);
125234287Sdim    strncpy(partialKey, subKey, partialKeyLength);
126234287Sdim    partialKey[partialKeyLength] = '\0';
127234287Sdim    HKEY hTopKey = NULL;
128234287Sdim    lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ, &hTopKey);
129234287Sdim    if (lResult == ERROR_SUCCESS) {
130234287Sdim      char keyName[256];
131234287Sdim      int bestIndex = -1;
132234287Sdim      double bestValue = 0.0;
133234287Sdim      DWORD index, size = sizeof(keyName) - 1;
134234287Sdim      for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL,
135234287Sdim          NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
136234287Sdim        const char *sp = keyName;
137249423Sdim        while (*sp && !isDigit(*sp))
138234287Sdim          sp++;
139234287Sdim        if (!*sp)
140234287Sdim          continue;
141234287Sdim        const char *ep = sp + 1;
142249423Sdim        while (*ep && (isDigit(*ep) || (*ep == '.')))
143234287Sdim          ep++;
144234287Sdim        char numBuf[32];
145234287Sdim        strncpy(numBuf, sp, sizeof(numBuf) - 1);
146234287Sdim        numBuf[sizeof(numBuf) - 1] = '\0';
147234287Sdim        double value = strtod(numBuf, NULL);
148234287Sdim        if (value > bestValue) {
149234287Sdim          bestIndex = (int)index;
150234287Sdim          bestValue = value;
151234287Sdim          strcpy(bestName, keyName);
152234287Sdim        }
153234287Sdim        size = sizeof(keyName) - 1;
154234287Sdim      }
155234287Sdim      // If we found the highest versioned key, open the key and get the value.
156234287Sdim      if (bestIndex != -1) {
157234287Sdim        // Append rest of key.
158234287Sdim        strncat(bestName, nextKey, sizeof(bestName) - 1);
159234287Sdim        bestName[sizeof(bestName) - 1] = '\0';
160234287Sdim        // Open the chosen key path remainder.
161234287Sdim        lResult = RegOpenKeyEx(hTopKey, bestName, 0, KEY_READ, &hKey);
162234287Sdim        if (lResult == ERROR_SUCCESS) {
163234287Sdim          lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
164234287Sdim            (LPBYTE)value, &valueSize);
165234287Sdim          if (lResult == ERROR_SUCCESS)
166234287Sdim            returnValue = true;
167234287Sdim          RegCloseKey(hKey);
168234287Sdim        }
169234287Sdim      }
170234287Sdim      RegCloseKey(hTopKey);
171234287Sdim    }
172234287Sdim  } else {
173234287Sdim    lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ, &hKey);
174234287Sdim    if (lResult == ERROR_SUCCESS) {
175234287Sdim      lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
176234287Sdim        (LPBYTE)value, &valueSize);
177234287Sdim      if (lResult == ERROR_SUCCESS)
178234287Sdim        returnValue = true;
179234287Sdim      RegCloseKey(hKey);
180234287Sdim    }
181234287Sdim  }
182234287Sdim  return returnValue;
183234287Sdim}
184234287Sdim
185234287Sdim/// \brief Get Windows SDK installation directory.
186234287Sdimstatic bool getWindowsSDKDir(std::string &path) {
187234287Sdim  char windowsSDKInstallDir[256];
188234287Sdim  // Try the Windows registry.
189234287Sdim  bool hasSDKDir = getSystemRegistryString(
190234287Sdim   "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
191234287Sdim                                           "InstallationFolder",
192234287Sdim                                           windowsSDKInstallDir,
193234287Sdim                                           sizeof(windowsSDKInstallDir) - 1);
194234287Sdim    // If we have both vc80 and vc90, pick version we were compiled with.
195234287Sdim  if (hasSDKDir && windowsSDKInstallDir[0]) {
196234287Sdim    path = windowsSDKInstallDir;
197234287Sdim    return true;
198234287Sdim  }
199234287Sdim  return false;
200234287Sdim}
201234287Sdim
202234287Sdim  // Get Visual Studio installation directory.
203234287Sdimstatic bool getVisualStudioDir(std::string &path) {
204234287Sdim  // First check the environment variables that vsvars32.bat sets.
205234287Sdim  const char* vcinstalldir = getenv("VCINSTALLDIR");
206234287Sdim  if (vcinstalldir) {
207234287Sdim    char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC"));
208234287Sdim    if (p)
209234287Sdim      *p = '\0';
210234287Sdim    path = vcinstalldir;
211234287Sdim    return true;
212234287Sdim  }
213234287Sdim
214234287Sdim  char vsIDEInstallDir[256];
215234287Sdim  char vsExpressIDEInstallDir[256];
216234287Sdim  // Then try the windows registry.
217234287Sdim  bool hasVCDir = getSystemRegistryString(
218234287Sdim    "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
219234287Sdim    "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1);
220234287Sdim  bool hasVCExpressDir = getSystemRegistryString(
221234287Sdim    "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\$VERSION",
222234287Sdim    "InstallDir", vsExpressIDEInstallDir, sizeof(vsExpressIDEInstallDir) - 1);
223234287Sdim    // If we have both vc80 and vc90, pick version we were compiled with.
224234287Sdim  if (hasVCDir && vsIDEInstallDir[0]) {
225234287Sdim    char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE");
226234287Sdim    if (p)
227234287Sdim      *p = '\0';
228234287Sdim    path = vsIDEInstallDir;
229234287Sdim    return true;
230234287Sdim  }
231234287Sdim
232234287Sdim  if (hasVCExpressDir && vsExpressIDEInstallDir[0]) {
233234287Sdim    char *p = (char*)strstr(vsExpressIDEInstallDir, "\\Common7\\IDE");
234234287Sdim    if (p)
235234287Sdim      *p = '\0';
236234287Sdim    path = vsExpressIDEInstallDir;
237234287Sdim    return true;
238234287Sdim  }
239234287Sdim
240234287Sdim  // Try the environment.
241234287Sdim  const char *vs100comntools = getenv("VS100COMNTOOLS");
242234287Sdim  const char *vs90comntools = getenv("VS90COMNTOOLS");
243234287Sdim  const char *vs80comntools = getenv("VS80COMNTOOLS");
244234287Sdim  const char *vscomntools = NULL;
245234287Sdim
246234287Sdim  // Try to find the version that we were compiled with
247234287Sdim  if(false) {}
248234287Sdim  #if (_MSC_VER >= 1600)  // VC100
249234287Sdim  else if(vs100comntools) {
250234287Sdim    vscomntools = vs100comntools;
251234287Sdim  }
252234287Sdim  #elif (_MSC_VER == 1500) // VC80
253234287Sdim  else if(vs90comntools) {
254234287Sdim    vscomntools = vs90comntools;
255234287Sdim  }
256234287Sdim  #elif (_MSC_VER == 1400) // VC80
257234287Sdim  else if(vs80comntools) {
258234287Sdim    vscomntools = vs80comntools;
259234287Sdim  }
260234287Sdim  #endif
261234287Sdim  // Otherwise find any version we can
262234287Sdim  else if (vs100comntools)
263234287Sdim    vscomntools = vs100comntools;
264234287Sdim  else if (vs90comntools)
265234287Sdim    vscomntools = vs90comntools;
266234287Sdim  else if (vs80comntools)
267234287Sdim    vscomntools = vs80comntools;
268234287Sdim
269234287Sdim  if (vscomntools && *vscomntools) {
270234287Sdim    const char *p = strstr(vscomntools, "\\Common7\\Tools");
271234287Sdim    path = p ? std::string(vscomntools, p) : vscomntools;
272234287Sdim    return true;
273234287Sdim  }
274234287Sdim  return false;
275234287Sdim}
276234287Sdim
277234287Sdim#endif // _MSC_VER
278234287Sdim
279234287Sdimvoid Windows::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
280234287Sdim                                        ArgStringList &CC1Args) const {
281234287Sdim  if (DriverArgs.hasArg(options::OPT_nostdinc))
282234287Sdim    return;
283234287Sdim
284234287Sdim  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
285234287Sdim    llvm::sys::Path P(getDriver().ResourceDir);
286234287Sdim    P.appendComponent("include");
287234287Sdim    addSystemInclude(DriverArgs, CC1Args, P.str());
288234287Sdim  }
289234287Sdim
290234287Sdim  if (DriverArgs.hasArg(options::OPT_nostdlibinc))
291234287Sdim    return;
292234287Sdim
293234287Sdim#ifdef _MSC_VER
294234287Sdim  // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat.
295234287Sdim  if (const char *cl_include_dir = getenv("INCLUDE")) {
296234287Sdim    SmallVector<StringRef, 8> Dirs;
297234287Sdim    StringRef(cl_include_dir).split(Dirs, ";");
298234287Sdim    int n = 0;
299234287Sdim    for (SmallVectorImpl<StringRef>::iterator I = Dirs.begin(), E = Dirs.end();
300234287Sdim         I != E; ++I) {
301234287Sdim      StringRef d = *I;
302234287Sdim      if (d.size() == 0)
303234287Sdim        continue;
304234287Sdim      ++n;
305234287Sdim      addSystemInclude(DriverArgs, CC1Args, d);
306234287Sdim    }
307234287Sdim    if (n) return;
308234287Sdim  }
309234287Sdim
310234287Sdim  std::string VSDir;
311234287Sdim  std::string WindowsSDKDir;
312234287Sdim
313234287Sdim  // When built with access to the proper Windows APIs, try to actually find
314234287Sdim  // the correct include paths first.
315234287Sdim  if (getVisualStudioDir(VSDir)) {
316234287Sdim    addSystemInclude(DriverArgs, CC1Args, VSDir + "\\VC\\include");
317234287Sdim    if (getWindowsSDKDir(WindowsSDKDir))
318234287Sdim      addSystemInclude(DriverArgs, CC1Args, WindowsSDKDir + "\\include");
319234287Sdim    else
320234287Sdim      addSystemInclude(DriverArgs, CC1Args,
321234287Sdim                       VSDir + "\\VC\\PlatformSDK\\Include");
322234287Sdim    return;
323234287Sdim  }
324234287Sdim#endif // _MSC_VER
325234287Sdim
326234287Sdim  // As a fallback, select default install paths.
327234287Sdim  const StringRef Paths[] = {
328234287Sdim    "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
329234287Sdim    "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
330234287Sdim    "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
331234287Sdim    "C:/Program Files/Microsoft Visual Studio 8/VC/include",
332234287Sdim    "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
333234287Sdim  };
334234287Sdim  addSystemIncludes(DriverArgs, CC1Args, Paths);
335234287Sdim}
336234287Sdim
337234287Sdimvoid Windows::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
338234287Sdim                                           ArgStringList &CC1Args) const {
339234287Sdim  // FIXME: There should probably be logic here to find libc++ on Windows.
340234287Sdim}
341