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"
11252723Sdim#include "clang/Basic/CharInfo.h"
12252723Sdim#include "clang/Basic/Version.h"
13234287Sdim#include "clang/Driver/Compilation.h"
14234287Sdim#include "clang/Driver/Driver.h"
15252723Sdim#include "clang/Driver/DriverDiagnostic.h"
16234287Sdim#include "clang/Driver/Options.h"
17263509Sdim#include "llvm/Option/Arg.h"
18263509Sdim#include "llvm/Option/ArgList.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;
34263509Sdimusing namespace llvm::opt;
35234287Sdim
36252723SdimWindows::Windows(const Driver &D, const llvm::Triple& Triple,
37252723Sdim                 const ArgList &Args)
38252723Sdim  : ToolChain(D, Triple, Args) {
39234287Sdim}
40234287Sdim
41252723SdimTool *Windows::buildLinker() const {
42252723Sdim  return new tools::visualstudio::Link(*this);
43252723Sdim}
44234287Sdim
45252723SdimTool *Windows::buildAssembler() const {
46252723Sdim  if (getTriple().getEnvironment() == llvm::Triple::MachO)
47252723Sdim    return new tools::darwin::Assemble(*this);
48263509Sdim  getDriver().Diag(clang::diag::err_no_external_assembler);
49252723Sdim  return NULL;
50234287Sdim}
51234287Sdim
52234287Sdimbool Windows::IsIntegratedAssemblerDefault() const {
53234287Sdim  return true;
54234287Sdim}
55234287Sdim
56234287Sdimbool Windows::IsUnwindTablesDefault() const {
57245431Sdim  return getArch() == llvm::Triple::x86_64;
58234287Sdim}
59234287Sdim
60245431Sdimbool Windows::isPICDefault() const {
61245431Sdim  return getArch() == llvm::Triple::x86_64;
62234287Sdim}
63234287Sdim
64252723Sdimbool Windows::isPIEDefault() const {
65252723Sdim  return false;
66252723Sdim}
67252723Sdim
68245431Sdimbool Windows::isPICDefaultForced() const {
69245431Sdim  return getArch() == llvm::Triple::x86_64;
70234287Sdim}
71234287Sdim
72234287Sdim// FIXME: This probably should goto to some platform utils place.
73234287Sdim#ifdef _MSC_VER
74234287Sdim
75234287Sdim/// \brief Read registry string.
76234287Sdim/// This also supports a means to look for high-versioned keys by use
77234287Sdim/// of a $VERSION placeholder in the key path.
78234287Sdim/// $VERSION in the key path is a placeholder for the version number,
79234287Sdim/// causing the highest value path to be searched for and used.
80234287Sdim/// I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
81234287Sdim/// There can be additional characters in the component.  Only the numberic
82234287Sdim/// characters are compared.
83234287Sdimstatic bool getSystemRegistryString(const char *keyPath, const char *valueName,
84234287Sdim                                    char *value, size_t maxLength) {
85234287Sdim  HKEY hRootKey = NULL;
86234287Sdim  HKEY hKey = NULL;
87234287Sdim  const char* subKey = NULL;
88234287Sdim  DWORD valueType;
89234287Sdim  DWORD valueSize = maxLength - 1;
90234287Sdim  long lResult;
91234287Sdim  bool returnValue = false;
92234287Sdim
93234287Sdim  if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) {
94234287Sdim    hRootKey = HKEY_CLASSES_ROOT;
95234287Sdim    subKey = keyPath + 18;
96234287Sdim  } else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) {
97234287Sdim    hRootKey = HKEY_USERS;
98234287Sdim    subKey = keyPath + 11;
99234287Sdim  } else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) {
100234287Sdim    hRootKey = HKEY_LOCAL_MACHINE;
101234287Sdim    subKey = keyPath + 19;
102234287Sdim  } else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) {
103234287Sdim    hRootKey = HKEY_CURRENT_USER;
104234287Sdim    subKey = keyPath + 18;
105234287Sdim  } else {
106234287Sdim    return false;
107234287Sdim  }
108234287Sdim
109234287Sdim  const char *placeHolder = strstr(subKey, "$VERSION");
110234287Sdim  char bestName[256];
111234287Sdim  bestName[0] = '\0';
112234287Sdim  // If we have a $VERSION placeholder, do the highest-version search.
113234287Sdim  if (placeHolder) {
114234287Sdim    const char *keyEnd = placeHolder - 1;
115234287Sdim    const char *nextKey = placeHolder;
116234287Sdim    // Find end of previous key.
117234287Sdim    while ((keyEnd > subKey) && (*keyEnd != '\\'))
118234287Sdim      keyEnd--;
119234287Sdim    // Find end of key containing $VERSION.
120234287Sdim    while (*nextKey && (*nextKey != '\\'))
121234287Sdim      nextKey++;
122234287Sdim    size_t partialKeyLength = keyEnd - subKey;
123234287Sdim    char partialKey[256];
124234287Sdim    if (partialKeyLength > sizeof(partialKey))
125234287Sdim      partialKeyLength = sizeof(partialKey);
126234287Sdim    strncpy(partialKey, subKey, partialKeyLength);
127234287Sdim    partialKey[partialKeyLength] = '\0';
128234287Sdim    HKEY hTopKey = NULL;
129263509Sdim    lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY,
130263509Sdim                           &hTopKey);
131234287Sdim    if (lResult == ERROR_SUCCESS) {
132234287Sdim      char keyName[256];
133234287Sdim      int bestIndex = -1;
134234287Sdim      double bestValue = 0.0;
135234287Sdim      DWORD index, size = sizeof(keyName) - 1;
136234287Sdim      for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL,
137234287Sdim          NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
138234287Sdim        const char *sp = keyName;
139252723Sdim        while (*sp && !isDigit(*sp))
140234287Sdim          sp++;
141234287Sdim        if (!*sp)
142234287Sdim          continue;
143234287Sdim        const char *ep = sp + 1;
144252723Sdim        while (*ep && (isDigit(*ep) || (*ep == '.')))
145234287Sdim          ep++;
146234287Sdim        char numBuf[32];
147234287Sdim        strncpy(numBuf, sp, sizeof(numBuf) - 1);
148234287Sdim        numBuf[sizeof(numBuf) - 1] = '\0';
149263509Sdim        double dvalue = strtod(numBuf, NULL);
150263509Sdim        if (dvalue > bestValue) {
151263509Sdim          // Test that InstallDir is indeed there before keeping this index.
152263509Sdim          // Open the chosen key path remainder.
153234287Sdim          strcpy(bestName, keyName);
154263509Sdim          // Append rest of key.
155263509Sdim          strncat(bestName, nextKey, sizeof(bestName) - 1);
156263509Sdim          bestName[sizeof(bestName) - 1] = '\0';
157263509Sdim          lResult = RegOpenKeyEx(hTopKey, bestName, 0,
158263509Sdim                                 KEY_READ | KEY_WOW64_32KEY, &hKey);
159263509Sdim          if (lResult == ERROR_SUCCESS) {
160263509Sdim            lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
161263509Sdim              (LPBYTE)value, &valueSize);
162263509Sdim            if (lResult == ERROR_SUCCESS) {
163263509Sdim              bestIndex = (int)index;
164263509Sdim              bestValue = dvalue;
165263509Sdim              returnValue = true;
166263509Sdim            }
167263509Sdim            RegCloseKey(hKey);
168263509Sdim          }
169234287Sdim        }
170234287Sdim        size = sizeof(keyName) - 1;
171234287Sdim      }
172234287Sdim      RegCloseKey(hTopKey);
173234287Sdim    }
174234287Sdim  } else {
175263509Sdim    lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ | KEY_WOW64_32KEY,
176263509Sdim                           &hKey);
177234287Sdim    if (lResult == ERROR_SUCCESS) {
178234287Sdim      lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
179234287Sdim        (LPBYTE)value, &valueSize);
180234287Sdim      if (lResult == ERROR_SUCCESS)
181234287Sdim        returnValue = true;
182234287Sdim      RegCloseKey(hKey);
183234287Sdim    }
184234287Sdim  }
185234287Sdim  return returnValue;
186234287Sdim}
187234287Sdim
188234287Sdim/// \brief Get Windows SDK installation directory.
189234287Sdimstatic bool getWindowsSDKDir(std::string &path) {
190234287Sdim  char windowsSDKInstallDir[256];
191234287Sdim  // Try the Windows registry.
192234287Sdim  bool hasSDKDir = getSystemRegistryString(
193234287Sdim   "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
194234287Sdim                                           "InstallationFolder",
195234287Sdim                                           windowsSDKInstallDir,
196234287Sdim                                           sizeof(windowsSDKInstallDir) - 1);
197234287Sdim    // If we have both vc80 and vc90, pick version we were compiled with.
198234287Sdim  if (hasSDKDir && windowsSDKInstallDir[0]) {
199234287Sdim    path = windowsSDKInstallDir;
200234287Sdim    return true;
201234287Sdim  }
202234287Sdim  return false;
203234287Sdim}
204234287Sdim
205234287Sdim  // Get Visual Studio installation directory.
206234287Sdimstatic bool getVisualStudioDir(std::string &path) {
207234287Sdim  // First check the environment variables that vsvars32.bat sets.
208234287Sdim  const char* vcinstalldir = getenv("VCINSTALLDIR");
209234287Sdim  if (vcinstalldir) {
210234287Sdim    char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC"));
211234287Sdim    if (p)
212234287Sdim      *p = '\0';
213234287Sdim    path = vcinstalldir;
214234287Sdim    return true;
215234287Sdim  }
216234287Sdim
217234287Sdim  char vsIDEInstallDir[256];
218234287Sdim  char vsExpressIDEInstallDir[256];
219234287Sdim  // Then try the windows registry.
220234287Sdim  bool hasVCDir = getSystemRegistryString(
221234287Sdim    "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
222234287Sdim    "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1);
223234287Sdim  bool hasVCExpressDir = getSystemRegistryString(
224234287Sdim    "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\$VERSION",
225234287Sdim    "InstallDir", vsExpressIDEInstallDir, sizeof(vsExpressIDEInstallDir) - 1);
226234287Sdim    // If we have both vc80 and vc90, pick version we were compiled with.
227234287Sdim  if (hasVCDir && vsIDEInstallDir[0]) {
228234287Sdim    char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE");
229234287Sdim    if (p)
230234287Sdim      *p = '\0';
231234287Sdim    path = vsIDEInstallDir;
232234287Sdim    return true;
233234287Sdim  }
234234287Sdim
235234287Sdim  if (hasVCExpressDir && vsExpressIDEInstallDir[0]) {
236234287Sdim    char *p = (char*)strstr(vsExpressIDEInstallDir, "\\Common7\\IDE");
237234287Sdim    if (p)
238234287Sdim      *p = '\0';
239234287Sdim    path = vsExpressIDEInstallDir;
240234287Sdim    return true;
241234287Sdim  }
242234287Sdim
243234287Sdim  // Try the environment.
244234287Sdim  const char *vs100comntools = getenv("VS100COMNTOOLS");
245234287Sdim  const char *vs90comntools = getenv("VS90COMNTOOLS");
246234287Sdim  const char *vs80comntools = getenv("VS80COMNTOOLS");
247234287Sdim  const char *vscomntools = NULL;
248234287Sdim
249234287Sdim  // Try to find the version that we were compiled with
250234287Sdim  if(false) {}
251234287Sdim  #if (_MSC_VER >= 1600)  // VC100
252234287Sdim  else if(vs100comntools) {
253234287Sdim    vscomntools = vs100comntools;
254234287Sdim  }
255234287Sdim  #elif (_MSC_VER == 1500) // VC80
256234287Sdim  else if(vs90comntools) {
257234287Sdim    vscomntools = vs90comntools;
258234287Sdim  }
259234287Sdim  #elif (_MSC_VER == 1400) // VC80
260234287Sdim  else if(vs80comntools) {
261234287Sdim    vscomntools = vs80comntools;
262234287Sdim  }
263234287Sdim  #endif
264234287Sdim  // Otherwise find any version we can
265234287Sdim  else if (vs100comntools)
266234287Sdim    vscomntools = vs100comntools;
267234287Sdim  else if (vs90comntools)
268234287Sdim    vscomntools = vs90comntools;
269234287Sdim  else if (vs80comntools)
270234287Sdim    vscomntools = vs80comntools;
271234287Sdim
272234287Sdim  if (vscomntools && *vscomntools) {
273234287Sdim    const char *p = strstr(vscomntools, "\\Common7\\Tools");
274234287Sdim    path = p ? std::string(vscomntools, p) : vscomntools;
275234287Sdim    return true;
276234287Sdim  }
277234287Sdim  return false;
278234287Sdim}
279234287Sdim
280234287Sdim#endif // _MSC_VER
281234287Sdim
282234287Sdimvoid Windows::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
283234287Sdim                                        ArgStringList &CC1Args) const {
284234287Sdim  if (DriverArgs.hasArg(options::OPT_nostdinc))
285234287Sdim    return;
286234287Sdim
287234287Sdim  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
288263509Sdim    SmallString<128> P(getDriver().ResourceDir);
289263509Sdim    llvm::sys::path::append(P, "include");
290234287Sdim    addSystemInclude(DriverArgs, CC1Args, P.str());
291234287Sdim  }
292234287Sdim
293234287Sdim  if (DriverArgs.hasArg(options::OPT_nostdlibinc))
294234287Sdim    return;
295234287Sdim
296234287Sdim#ifdef _MSC_VER
297234287Sdim  // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat.
298234287Sdim  if (const char *cl_include_dir = getenv("INCLUDE")) {
299234287Sdim    SmallVector<StringRef, 8> Dirs;
300234287Sdim    StringRef(cl_include_dir).split(Dirs, ";");
301234287Sdim    int n = 0;
302234287Sdim    for (SmallVectorImpl<StringRef>::iterator I = Dirs.begin(), E = Dirs.end();
303234287Sdim         I != E; ++I) {
304234287Sdim      StringRef d = *I;
305234287Sdim      if (d.size() == 0)
306234287Sdim        continue;
307234287Sdim      ++n;
308234287Sdim      addSystemInclude(DriverArgs, CC1Args, d);
309234287Sdim    }
310234287Sdim    if (n) return;
311234287Sdim  }
312234287Sdim
313234287Sdim  std::string VSDir;
314234287Sdim  std::string WindowsSDKDir;
315234287Sdim
316234287Sdim  // When built with access to the proper Windows APIs, try to actually find
317234287Sdim  // the correct include paths first.
318234287Sdim  if (getVisualStudioDir(VSDir)) {
319234287Sdim    addSystemInclude(DriverArgs, CC1Args, VSDir + "\\VC\\include");
320234287Sdim    if (getWindowsSDKDir(WindowsSDKDir))
321234287Sdim      addSystemInclude(DriverArgs, CC1Args, WindowsSDKDir + "\\include");
322234287Sdim    else
323234287Sdim      addSystemInclude(DriverArgs, CC1Args,
324234287Sdim                       VSDir + "\\VC\\PlatformSDK\\Include");
325234287Sdim    return;
326234287Sdim  }
327234287Sdim#endif // _MSC_VER
328234287Sdim
329234287Sdim  // As a fallback, select default install paths.
330234287Sdim  const StringRef Paths[] = {
331234287Sdim    "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
332234287Sdim    "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
333234287Sdim    "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
334234287Sdim    "C:/Program Files/Microsoft Visual Studio 8/VC/include",
335234287Sdim    "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
336234287Sdim  };
337234287Sdim  addSystemIncludes(DriverArgs, CC1Args, Paths);
338234287Sdim}
339234287Sdim
340234287Sdimvoid Windows::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
341234287Sdim                                           ArgStringList &CC1Args) const {
342234287Sdim  // FIXME: There should probably be logic here to find libc++ on Windows.
343234287Sdim}
344