blob: 17fd6ac6f714bf99b46dd12af524a1551afa4e86 [file] [log] [blame]
Chandler Carruth1fc603e2011-12-17 23:10:01 +00001//===--- 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"
David Majnemere11d3732015-06-08 00:22:46 +000011#include "Tools.h"
Jordan Rosea7d03842013-02-08 22:30:41 +000012#include "clang/Basic/CharInfo.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000013#include "clang/Basic/Version.h"
Chandler Carruth1fc603e2011-12-17 23:10:01 +000014#include "clang/Driver/Compilation.h"
15#include "clang/Driver/Driver.h"
Rafael Espindola79764462013-03-24 15:06:53 +000016#include "clang/Driver/DriverDiagnostic.h"
Chandler Carruth1fc603e2011-12-17 23:10:01 +000017#include "clang/Driver/Options.h"
Zachary Turner0eaf8fc2014-10-22 20:40:28 +000018#include "llvm/ADT/StringExtras.h"
David L. Jones24fb20c2016-12-07 23:41:58 +000019#include "llvm/ADT/StringSwitch.h"
Alp Tokerf1ffc842014-06-22 04:31:15 +000020#include "llvm/Config/llvm-config.h"
Reid Kleckner898229a2013-06-14 17:17:23 +000021#include "llvm/Option/Arg.h"
22#include "llvm/Option/ArgList.h"
Adrian McCarthye4b26fc2016-05-13 23:20:11 +000023#include "llvm/Support/ConvertUTF.h"
Chandler Carruth1fc603e2011-12-17 23:10:01 +000024#include "llvm/Support/ErrorHandling.h"
Zachary Turner0eaf8fc2014-10-22 20:40:28 +000025#include "llvm/Support/FileSystem.h"
Mehdi Amini9670f842016-07-18 19:02:11 +000026#include "llvm/Support/Path.h"
Zachary Turner0eaf8fc2014-10-22 20:40:28 +000027#include "llvm/Support/Process.h"
Reid Kleckner6b7156b2015-01-23 19:16:25 +000028#include <cstdio>
29
Reid Kleckner723fabf2017-02-02 19:29:46 +000030// Include the necessary headers to interface with the Windows registry and
31// environment.
Reid Klecknerbf183552017-02-02 19:36:22 +000032#if defined(LLVM_ON_WIN32)
33#define USE_WIN32
34#endif
35
Alp Tokerfcce1832014-06-22 03:27:45 +000036#ifdef USE_WIN32
Chandler Carruth1fc603e2011-12-17 23:10:01 +000037 #define WIN32_LEAN_AND_MEAN
38 #define NOGDI
Yaron Keren7fc6f1e2014-12-04 21:46:50 +000039 #ifndef NOMINMAX
40 #define NOMINMAX
41 #endif
Logan Chien733e3c62014-06-24 16:18:10 +000042 #include <windows.h>
Chandler Carruth1fc603e2011-12-17 23:10:01 +000043#endif
44
45using namespace clang::driver;
46using namespace clang::driver::toolchains;
47using namespace clang;
Reid Kleckner898229a2013-06-14 17:17:23 +000048using namespace llvm::opt;
Chandler Carruth1fc603e2011-12-17 23:10:01 +000049
Reid Klecknerbf183552017-02-02 19:36:22 +000050MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
Saleem Abdulrasool819f3912014-10-22 02:37:29 +000051 const ArgList &Args)
Justin Lebar58891902017-01-05 16:52:29 +000052 : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args) {
Zachary Turner719f58c2014-12-01 23:06:47 +000053 getProgramPaths().push_back(getDriver().getInstalledDir());
54 if (getDriver().getInstalledDir() != getDriver().Dir)
55 getProgramPaths().push_back(getDriver().Dir);
Hans Wennborg1cc6cce2013-08-30 09:42:06 +000056}
57
Saleem Abdulrasool819f3912014-10-22 02:37:29 +000058Tool *MSVCToolChain::buildLinker() const {
Douglas Katzman95354292015-06-23 20:42:09 +000059 return new tools::visualstudio::Linker(*this);
Hans Wennborg1cc6cce2013-08-30 09:42:06 +000060}
61
Saleem Abdulrasool819f3912014-10-22 02:37:29 +000062Tool *MSVCToolChain::buildAssembler() const {
Saleem Abdulrasool377066a2014-03-27 22:50:18 +000063 if (getTriple().isOSBinFormatMachO())
Douglas Katzman95354292015-06-23 20:42:09 +000064 return new tools::darwin::Assembler(*this);
Alp Tokerc8d4f0f2013-11-22 08:27:46 +000065 getDriver().Diag(clang::diag::err_no_external_assembler);
Craig Topper92fc2df2014-05-17 16:56:41 +000066 return nullptr;
Hans Wennborg1cc6cce2013-08-30 09:42:06 +000067}
68
Saleem Abdulrasool819f3912014-10-22 02:37:29 +000069bool MSVCToolChain::IsIntegratedAssemblerDefault() const {
Hans Wennborg1cc6cce2013-08-30 09:42:06 +000070 return true;
71}
72
Saleem Abdulrasool819f3912014-10-22 02:37:29 +000073bool MSVCToolChain::IsUnwindTablesDefault() const {
Reid Kleckner6b3a9402014-09-04 18:13:12 +000074 // Emit unwind tables by default on Win64. All non-x86_32 Windows platforms
75 // such as ARM and PPC actually require unwind tables, but LLVM doesn't know
76 // how to generate them yet.
Akira Hatanakae4218132016-05-05 01:41:07 +000077
78 // Don't emit unwind tables by default for MachO targets.
79 if (getTriple().isOSBinFormatMachO())
80 return false;
81
Reid Kleckner6b3a9402014-09-04 18:13:12 +000082 return getArch() == llvm::Triple::x86_64;
Hans Wennborg1cc6cce2013-08-30 09:42:06 +000083}
84
Reid Kleckner8c190832016-12-28 17:41:36 +000085bool MSVCToolChain::isPICDefault() const {
86 return getArch() == llvm::Triple::x86_64;
87}
88
89bool MSVCToolChain::isPIEDefault() const {
90 return false;
91}
92
93bool MSVCToolChain::isPICDefaultForced() const {
94 return getArch() == llvm::Triple::x86_64;
95}
96
Justin Lebar58891902017-01-05 16:52:29 +000097void MSVCToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
98 ArgStringList &CC1Args) const {
99 CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
100}
101
102void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const {
103 CudaInstallation.print(OS);
104}
105
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000106#ifdef USE_WIN32
107static bool readFullStringValue(HKEY hkey, const char *valueName,
108 std::string &value) {
Aaron Ballmanb06a3592016-06-23 14:33:53 +0000109 std::wstring WideValueName;
110 if (!llvm::ConvertUTF8toWide(valueName, WideValueName))
111 return false;
112
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000113 DWORD result = 0;
114 DWORD valueSize = 0;
115 DWORD type = 0;
116 // First just query for the required size.
Aaron Ballmanb06a3592016-06-23 14:33:53 +0000117 result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, &type, NULL,
118 &valueSize);
119 if (result != ERROR_SUCCESS || type != REG_SZ || !valueSize)
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000120 return false;
121 std::vector<BYTE> buffer(valueSize);
Aaron Ballmanb06a3592016-06-23 14:33:53 +0000122 result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, NULL, &buffer[0],
123 &valueSize);
124 if (result == ERROR_SUCCESS) {
125 std::wstring WideValue(reinterpret_cast<const wchar_t *>(buffer.data()),
126 valueSize / sizeof(wchar_t));
Zachary Turnere78a3472016-07-28 17:13:32 +0000127 if (valueSize && WideValue.back() == L'\0') {
Etienne Bergeron982a3bc2016-08-30 18:38:25 +0000128 WideValue.pop_back();
Zachary Turnere78a3472016-07-28 17:13:32 +0000129 }
Aaron Ballmanb06a3592016-06-23 14:33:53 +0000130 // The destination buffer must be empty as an invariant of the conversion
131 // function; but this function is sometimes called in a loop that passes in
132 // the same buffer, however. Simply clear it out so we can overwrite it.
133 value.clear();
134 return llvm::convertWideToUTF8(WideValue, value);
135 }
136 return false;
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000137}
138#endif
139
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000140/// \brief Read registry string.
141/// This also supports a means to look for high-versioned keys by use
142/// of a $VERSION placeholder in the key path.
143/// $VERSION in the key path is a placeholder for the version number,
144/// causing the highest value path to be searched for and used.
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000145/// I.e. "SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
146/// There can be additional characters in the component. Only the numeric
147/// characters are compared. This function only searches HKLM.
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000148static bool getSystemRegistryString(const char *keyPath, const char *valueName,
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000149 std::string &value, std::string *phValue) {
Alp Tokerfcce1832014-06-22 03:27:45 +0000150#ifndef USE_WIN32
151 return false;
152#else
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000153 HKEY hRootKey = HKEY_LOCAL_MACHINE;
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000154 HKEY hKey = NULL;
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000155 long lResult;
156 bool returnValue = false;
157
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000158 const char *placeHolder = strstr(keyPath, "$VERSION");
159 std::string bestName;
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000160 // If we have a $VERSION placeholder, do the highest-version search.
161 if (placeHolder) {
162 const char *keyEnd = placeHolder - 1;
163 const char *nextKey = placeHolder;
164 // Find end of previous key.
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000165 while ((keyEnd > keyPath) && (*keyEnd != '\\'))
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000166 keyEnd--;
167 // Find end of key containing $VERSION.
168 while (*nextKey && (*nextKey != '\\'))
169 nextKey++;
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000170 size_t partialKeyLength = keyEnd - keyPath;
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000171 char partialKey[256];
Daniel Marjamakie1146692016-01-27 07:33:50 +0000172 if (partialKeyLength >= sizeof(partialKey))
173 partialKeyLength = sizeof(partialKey) - 1;
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000174 strncpy(partialKey, keyPath, partialKeyLength);
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000175 partialKey[partialKeyLength] = '\0';
176 HKEY hTopKey = NULL;
Aaron Ballmanb06a3592016-06-23 14:33:53 +0000177 lResult = RegOpenKeyExA(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY,
178 &hTopKey);
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000179 if (lResult == ERROR_SUCCESS) {
180 char keyName[256];
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000181 double bestValue = 0.0;
182 DWORD index, size = sizeof(keyName) - 1;
Aaron Ballmanb06a3592016-06-23 14:33:53 +0000183 for (index = 0; RegEnumKeyExA(hTopKey, index, keyName, &size, NULL, NULL,
184 NULL, NULL) == ERROR_SUCCESS;
185 index++) {
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000186 const char *sp = keyName;
Jordan Rosea7d03842013-02-08 22:30:41 +0000187 while (*sp && !isDigit(*sp))
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000188 sp++;
189 if (!*sp)
190 continue;
191 const char *ep = sp + 1;
Jordan Rosea7d03842013-02-08 22:30:41 +0000192 while (*ep && (isDigit(*ep) || (*ep == '.')))
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000193 ep++;
194 char numBuf[32];
195 strncpy(numBuf, sp, sizeof(numBuf) - 1);
196 numBuf[sizeof(numBuf) - 1] = '\0';
Hans Wennborgd2192312013-10-10 18:03:08 +0000197 double dvalue = strtod(numBuf, NULL);
198 if (dvalue > bestValue) {
199 // Test that InstallDir is indeed there before keeping this index.
200 // Open the chosen key path remainder.
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000201 bestName = keyName;
Hans Wennborgd2192312013-10-10 18:03:08 +0000202 // Append rest of key.
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000203 bestName.append(nextKey);
Aaron Ballmanb06a3592016-06-23 14:33:53 +0000204 lResult = RegOpenKeyExA(hTopKey, bestName.c_str(), 0,
205 KEY_READ | KEY_WOW64_32KEY, &hKey);
Hans Wennborgd2192312013-10-10 18:03:08 +0000206 if (lResult == ERROR_SUCCESS) {
Zachary Turnere78a3472016-07-28 17:13:32 +0000207 if (readFullStringValue(hKey, valueName, value)) {
Hans Wennborgd2192312013-10-10 18:03:08 +0000208 bestValue = dvalue;
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000209 if (phValue)
210 *phValue = bestName;
Hans Wennborgd2192312013-10-10 18:03:08 +0000211 returnValue = true;
212 }
213 RegCloseKey(hKey);
214 }
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000215 }
216 size = sizeof(keyName) - 1;
217 }
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000218 RegCloseKey(hTopKey);
219 }
220 } else {
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000221 lResult =
Aaron Ballmanb06a3592016-06-23 14:33:53 +0000222 RegOpenKeyExA(hRootKey, keyPath, 0, KEY_READ | KEY_WOW64_32KEY, &hKey);
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000223 if (lResult == ERROR_SUCCESS) {
Zachary Turnere78a3472016-07-28 17:13:32 +0000224 if (readFullStringValue(hKey, valueName, value))
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000225 returnValue = true;
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000226 if (phValue)
227 phValue->clear();
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000228 RegCloseKey(hKey);
229 }
230 }
231 return returnValue;
Alp Tokerfcce1832014-06-22 03:27:45 +0000232#endif // USE_WIN32
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000233}
234
Reid Klecknerbf183552017-02-02 19:36:22 +0000235// Convert LLVM's ArchType
236// to the corresponding name of Windows SDK libraries subfolder
237static StringRef getWindowsSDKArch(llvm::Triple::ArchType Arch) {
238 switch (Arch) {
239 case llvm::Triple::x86:
240 return "x86";
241 case llvm::Triple::x86_64:
242 return "x64";
243 case llvm::Triple::arm:
244 return "arm";
245 default:
246 return "";
247 }
248}
249
Igor Kudrinf2e75242015-09-24 05:16:36 +0000250// Find the most recent version of Universal CRT or Windows 10 SDK.
251// vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include
252// directory by name and uses the last one of the list.
253// So we compare entry names lexicographically to find the greatest one.
Reid Klecknerbf183552017-02-02 19:36:22 +0000254static bool getWindows10SDKVersion(const std::string &SDKPath,
255 std::string &SDKVersion) {
Igor Kudrinf2e75242015-09-24 05:16:36 +0000256 SDKVersion.clear();
257
258 std::error_code EC;
259 llvm::SmallString<128> IncludePath(SDKPath);
260 llvm::sys::path::append(IncludePath, "Include");
261 for (llvm::sys::fs::directory_iterator DirIt(IncludePath, EC), DirEnd;
262 DirIt != DirEnd && !EC; DirIt.increment(EC)) {
263 if (!llvm::sys::fs::is_directory(DirIt->path()))
264 continue;
265 StringRef CandidateName = llvm::sys::path::filename(DirIt->path());
266 // If WDK is installed, there could be subfolders like "wdf" in the
267 // "Include" directory.
268 // Allow only directories which names start with "10.".
269 if (!CandidateName.startswith("10."))
270 continue;
271 if (CandidateName > SDKVersion)
272 SDKVersion = CandidateName;
273 }
274
275 return !SDKVersion.empty();
276}
277
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000278/// \brief Get Windows SDK installation directory.
Reid Klecknerbf183552017-02-02 19:36:22 +0000279bool MSVCToolChain::getWindowsSDKDir(std::string &Path, int &Major,
280 std::string &WindowsSDKIncludeVersion,
281 std::string &WindowsSDKLibVersion) const {
Igor Kudrinf2e75242015-09-24 05:16:36 +0000282 std::string RegistrySDKVersion;
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000283 // Try the Windows registry.
Igor Kudrinf2e75242015-09-24 05:16:36 +0000284 if (!getSystemRegistryString(
285 "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
286 "InstallationFolder", Path, &RegistrySDKVersion))
287 return false;
288 if (Path.empty() || RegistrySDKVersion.empty())
289 return false;
290
291 WindowsSDKIncludeVersion.clear();
292 WindowsSDKLibVersion.clear();
293 Major = 0;
294 std::sscanf(RegistrySDKVersion.c_str(), "v%d.", &Major);
295 if (Major <= 7)
296 return true;
297 if (Major == 8) {
298 // Windows SDK 8.x installs libraries in a folder whose names depend on the
299 // version of the OS you're targeting. By default choose the newest, which
300 // usually corresponds to the version of the OS you've installed the SDK on.
301 const char *Tests[] = {"winv6.3", "win8", "win7"};
302 for (const char *Test : Tests) {
303 llvm::SmallString<128> TestPath(Path);
304 llvm::sys::path::append(TestPath, "Lib", Test);
305 if (llvm::sys::fs::exists(TestPath.c_str())) {
306 WindowsSDKLibVersion = Test;
307 break;
308 }
309 }
310 return !WindowsSDKLibVersion.empty();
311 }
312 if (Major == 10) {
Reid Klecknerbf183552017-02-02 19:36:22 +0000313 if (!getWindows10SDKVersion(Path, WindowsSDKIncludeVersion))
Igor Kudrinf2e75242015-09-24 05:16:36 +0000314 return false;
315 WindowsSDKLibVersion = WindowsSDKIncludeVersion;
316 return true;
317 }
318 // Unsupported SDK version
319 return false;
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000320}
321
Zachary Turner10d75b22014-10-22 20:40:43 +0000322// Gets the library path required to link against the Windows SDK.
323bool MSVCToolChain::getWindowsSDKLibraryPath(std::string &path) const {
324 std::string sdkPath;
325 int sdkMajor = 0;
Igor Kudrinf2e75242015-09-24 05:16:36 +0000326 std::string windowsSDKIncludeVersion;
327 std::string windowsSDKLibVersion;
Zachary Turner10d75b22014-10-22 20:40:43 +0000328
329 path.clear();
Igor Kudrinf2e75242015-09-24 05:16:36 +0000330 if (!getWindowsSDKDir(sdkPath, sdkMajor, windowsSDKIncludeVersion,
331 windowsSDKLibVersion))
Zachary Turner10d75b22014-10-22 20:40:43 +0000332 return false;
333
334 llvm::SmallString<128> libPath(sdkPath);
335 llvm::sys::path::append(libPath, "Lib");
Reid Klecknerbf183552017-02-02 19:36:22 +0000336 if (sdkMajor <= 7) {
Zachary Turner10d75b22014-10-22 20:40:43 +0000337 switch (getArch()) {
Reid Klecknerbf183552017-02-02 19:36:22 +0000338 // In Windows SDK 7.x, x86 libraries are directly in the Lib folder.
Zachary Turner10d75b22014-10-22 20:40:43 +0000339 case llvm::Triple::x86:
340 break;
341 case llvm::Triple::x86_64:
342 llvm::sys::path::append(libPath, "x64");
343 break;
344 case llvm::Triple::arm:
345 // It is not necessary to link against Windows SDK 7.x when targeting ARM.
346 return false;
347 default:
348 return false;
349 }
Reid Klecknerbf183552017-02-02 19:36:22 +0000350 } else {
351 const StringRef archName = getWindowsSDKArch(getArch());
352 if (archName.empty())
353 return false;
354 llvm::sys::path::append(libPath, windowsSDKLibVersion, "um", archName);
Zachary Turner10d75b22014-10-22 20:40:43 +0000355 }
356
357 path = libPath.str();
358 return true;
359}
360
Reid Kleckner7531f7d2015-09-11 00:09:39 +0000361// Check if the Include path of a specified version of Visual Studio contains
362// specific header files. If not, they are probably shipped with Universal CRT.
Reid Klecknerbf183552017-02-02 19:36:22 +0000363bool clang::driver::toolchains::MSVCToolChain::useUniversalCRT(
364 std::string &VisualStudioDir) const {
365 llvm::SmallString<128> TestPath(VisualStudioDir);
366 llvm::sys::path::append(TestPath, "VC\\include\\stdlib.h");
367
Reid Kleckner7531f7d2015-09-11 00:09:39 +0000368 return !llvm::sys::fs::exists(TestPath);
369}
370
Reid Klecknerbf183552017-02-02 19:36:22 +0000371bool MSVCToolChain::getUniversalCRTSdkDir(std::string &Path,
372 std::string &UCRTVersion) const {
Reid Kleckner7531f7d2015-09-11 00:09:39 +0000373 // vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry
374 // for the specific key "KitsRoot10". So do we.
375 if (!getSystemRegistryString(
Reid Klecknerbf183552017-02-02 19:36:22 +0000376 "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10",
377 Path, nullptr))
Reid Kleckner7531f7d2015-09-11 00:09:39 +0000378 return false;
379
Reid Klecknerbf183552017-02-02 19:36:22 +0000380 return getWindows10SDKVersion(Path, UCRTVersion);
Reid Kleckner7531f7d2015-09-11 00:09:39 +0000381}
382
383bool MSVCToolChain::getUniversalCRTLibraryPath(std::string &Path) const {
384 std::string UniversalCRTSdkPath;
385 std::string UCRTVersion;
386
387 Path.clear();
388 if (!getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion))
389 return false;
390
Reid Klecknerbf183552017-02-02 19:36:22 +0000391 StringRef ArchName = getWindowsSDKArch(getArch());
Reid Kleckner7531f7d2015-09-11 00:09:39 +0000392 if (ArchName.empty())
393 return false;
394
395 llvm::SmallString<128> LibPath(UniversalCRTSdkPath);
396 llvm::sys::path::append(LibPath, "Lib", UCRTVersion, "ucrt", ArchName);
397
398 Path = LibPath.str();
399 return true;
400}
401
Reid Klecknerbf183552017-02-02 19:36:22 +0000402// Get the location to use for Visual Studio binaries. The location priority
403// is: %VCINSTALLDIR% > %PATH% > newest copy of Visual Studio installed on
404// system (as reported by the registry).
405bool MSVCToolChain::getVisualStudioBinariesFolder(const char *clangProgramPath,
406 std::string &path) const {
407 path.clear();
408
409 SmallString<128> BinDir;
410
411 // First check the environment variables that vsvars32.bat sets.
412 llvm::Optional<std::string> VcInstallDir =
413 llvm::sys::Process::GetEnv("VCINSTALLDIR");
414 if (VcInstallDir.hasValue()) {
415 BinDir = VcInstallDir.getValue();
416 llvm::sys::path::append(BinDir, "bin");
417 } else {
418 // Next walk the PATH, trying to find a cl.exe in the path. If we find one,
419 // use that. However, make sure it's not clang's cl.exe.
420 llvm::Optional<std::string> OptPath = llvm::sys::Process::GetEnv("PATH");
421 if (OptPath.hasValue()) {
422 const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
423 SmallVector<StringRef, 8> PathSegments;
424 llvm::SplitString(OptPath.getValue(), PathSegments, EnvPathSeparatorStr);
425
426 for (StringRef PathSegment : PathSegments) {
427 if (PathSegment.empty())
428 continue;
429
430 SmallString<128> FilePath(PathSegment);
431 llvm::sys::path::append(FilePath, "cl.exe");
432 // Checking if cl.exe exists is a small optimization over calling
433 // can_execute, which really only checks for existence but will also do
434 // extra checks for cl.exe.exe. These add up when walking a long path.
435 if (llvm::sys::fs::exists(FilePath.c_str()) &&
436 !llvm::sys::fs::equivalent(FilePath.c_str(), clangProgramPath)) {
437 // If we found it on the PATH, use it exactly as is with no
438 // modifications.
439 path = PathSegment;
440 return true;
441 }
442 }
443 }
444
445 std::string installDir;
446 // With no VCINSTALLDIR and nothing on the PATH, if we can't find it in the
447 // registry then we have no choice but to fail.
448 if (!getVisualStudioInstallDir(installDir))
449 return false;
450
451 // Regardless of what binary we're ultimately trying to find, we make sure
452 // that this is a Visual Studio directory by checking for cl.exe. We use
453 // cl.exe instead of other binaries like link.exe because programs such as
454 // GnuWin32 also have a utility called link.exe, so cl.exe is the least
455 // ambiguous.
456 BinDir = installDir;
457 llvm::sys::path::append(BinDir, "VC", "bin");
458 SmallString<128> ClPath(BinDir);
459 llvm::sys::path::append(ClPath, "cl.exe");
460
461 if (!llvm::sys::fs::can_execute(ClPath.c_str()))
462 return false;
463 }
464
465 if (BinDir.empty())
466 return false;
467
468 switch (getArch()) {
469 case llvm::Triple::x86:
470 break;
471 case llvm::Triple::x86_64:
472 llvm::sys::path::append(BinDir, "amd64");
473 break;
474 case llvm::Triple::arm:
475 llvm::sys::path::append(BinDir, "arm");
476 break;
477 default:
478 // Whatever this is, Visual Studio doesn't have a toolchain for it.
479 return false;
480 }
481 path = BinDir.str();
482 return true;
483}
484
485VersionTuple MSVCToolChain::getMSVCVersionFromTriple() const {
David L. Jones24fb20c2016-12-07 23:41:58 +0000486 unsigned Major, Minor, Micro;
Reid Klecknerbf183552017-02-02 19:36:22 +0000487 getTriple().getEnvironmentVersion(Major, Minor, Micro);
David L. Jones24fb20c2016-12-07 23:41:58 +0000488 if (Major || Minor || Micro)
489 return VersionTuple(Major, Minor, Micro);
490 return VersionTuple();
491}
492
Reid Klecknerbf183552017-02-02 19:36:22 +0000493VersionTuple MSVCToolChain::getMSVCVersionFromExe() const {
Adrian McCarthye4b26fc2016-05-13 23:20:11 +0000494 VersionTuple Version;
495#ifdef USE_WIN32
Reid Klecknerbf183552017-02-02 19:36:22 +0000496 std::string BinPath;
497 if (!getVisualStudioBinariesFolder("", BinPath))
498 return Version;
499 SmallString<128> ClExe(BinPath);
Adrian McCarthye4b26fc2016-05-13 23:20:11 +0000500 llvm::sys::path::append(ClExe, "cl.exe");
501
502 std::wstring ClExeWide;
503 if (!llvm::ConvertUTF8toWide(ClExe.c_str(), ClExeWide))
504 return Version;
505
506 const DWORD VersionSize = ::GetFileVersionInfoSizeW(ClExeWide.c_str(),
507 nullptr);
508 if (VersionSize == 0)
509 return Version;
510
511 SmallVector<uint8_t, 4 * 1024> VersionBlock(VersionSize);
512 if (!::GetFileVersionInfoW(ClExeWide.c_str(), 0, VersionSize,
513 VersionBlock.data()))
514 return Version;
515
516 VS_FIXEDFILEINFO *FileInfo = nullptr;
517 UINT FileInfoSize = 0;
518 if (!::VerQueryValueW(VersionBlock.data(), L"\\",
519 reinterpret_cast<LPVOID *>(&FileInfo), &FileInfoSize) ||
520 FileInfoSize < sizeof(*FileInfo))
521 return Version;
522
523 const unsigned Major = (FileInfo->dwFileVersionMS >> 16) & 0xFFFF;
524 const unsigned Minor = (FileInfo->dwFileVersionMS ) & 0xFFFF;
525 const unsigned Micro = (FileInfo->dwFileVersionLS >> 16) & 0xFFFF;
526
527 Version = VersionTuple(Major, Minor, Micro);
528#endif
529 return Version;
530}
531
Reid Klecknerbf183552017-02-02 19:36:22 +0000532// Get Visual Studio installation directory.
533bool MSVCToolChain::getVisualStudioInstallDir(std::string &path) const {
534 // First check the environment variables that vsvars32.bat sets.
535 if (llvm::Optional<std::string> VcInstallDir =
536 llvm::sys::Process::GetEnv("VCINSTALLDIR")) {
537 path = std::move(*VcInstallDir);
538 path = path.substr(0, path.find("\\VC"));
539 return true;
540 }
541
542 std::string vsIDEInstallDir;
543 std::string vsExpressIDEInstallDir;
544 // Then try the windows registry.
545 bool hasVCDir =
546 getSystemRegistryString("SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
547 "InstallDir", vsIDEInstallDir, nullptr);
548 if (hasVCDir && !vsIDEInstallDir.empty()) {
549 path = vsIDEInstallDir.substr(0, vsIDEInstallDir.find("\\Common7\\IDE"));
550 return true;
551 }
552
553 bool hasVCExpressDir =
554 getSystemRegistryString("SOFTWARE\\Microsoft\\VCExpress\\$VERSION",
555 "InstallDir", vsExpressIDEInstallDir, nullptr);
556 if (hasVCExpressDir && !vsExpressIDEInstallDir.empty()) {
557 path = vsExpressIDEInstallDir.substr(
558 0, vsIDEInstallDir.find("\\Common7\\IDE"));
559 return true;
560 }
561
562 // Try the environment.
563 std::string vcomntools;
564 if (llvm::Optional<std::string> vs120comntools =
565 llvm::sys::Process::GetEnv("VS120COMNTOOLS"))
566 vcomntools = std::move(*vs120comntools);
567 else if (llvm::Optional<std::string> vs100comntools =
568 llvm::sys::Process::GetEnv("VS100COMNTOOLS"))
569 vcomntools = std::move(*vs100comntools);
570 else if (llvm::Optional<std::string> vs90comntools =
571 llvm::sys::Process::GetEnv("VS90COMNTOOLS"))
572 vcomntools = std::move(*vs90comntools);
573 else if (llvm::Optional<std::string> vs80comntools =
574 llvm::sys::Process::GetEnv("VS80COMNTOOLS"))
575 vcomntools = std::move(*vs80comntools);
576
577 // Find any version we can.
578 if (!vcomntools.empty()) {
579 size_t p = vcomntools.find("\\Common7\\Tools");
580 if (p != std::string::npos)
581 vcomntools.resize(p);
582 path = std::move(vcomntools);
583 return true;
584 }
585 return false;
586}
587
Igor Kudrinf2e75242015-09-24 05:16:36 +0000588void MSVCToolChain::AddSystemIncludeWithSubfolder(
589 const ArgList &DriverArgs, ArgStringList &CC1Args,
590 const std::string &folder, const Twine &subfolder1, const Twine &subfolder2,
591 const Twine &subfolder3) const {
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000592 llvm::SmallString<128> path(folder);
Igor Kudrinf2e75242015-09-24 05:16:36 +0000593 llvm::sys::path::append(path, subfolder1, subfolder2, subfolder3);
Yaron Keren92e1b622015-03-18 10:17:07 +0000594 addSystemInclude(DriverArgs, CC1Args, path);
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000595}
596
Saleem Abdulrasool819f3912014-10-22 02:37:29 +0000597void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
598 ArgStringList &CC1Args) const {
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000599 if (DriverArgs.hasArg(options::OPT_nostdinc))
600 return;
601
602 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
Igor Kudrinf2e75242015-09-24 05:16:36 +0000603 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, getDriver().ResourceDir,
604 "include");
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000605 }
606
Nico Weberfd3e1ad2016-04-12 19:04:37 +0000607 // Add %INCLUDE%-like directories from the -imsvc flag.
608 for (const auto &Path : DriverArgs.getAllArgValues(options::OPT__SLASH_imsvc))
609 addSystemInclude(DriverArgs, CC1Args, Path);
610
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000611 if (DriverArgs.hasArg(options::OPT_nostdlibinc))
612 return;
613
Joao Matos792d7af2012-09-04 17:29:52 +0000614 // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat.
David Majnemer85c25b42016-07-24 17:44:03 +0000615 if (llvm::Optional<std::string> cl_include_dir =
616 llvm::sys::Process::GetEnv("INCLUDE")) {
Joao Matos792d7af2012-09-04 17:29:52 +0000617 SmallVector<StringRef, 8> Dirs;
David Majnemer85c25b42016-07-24 17:44:03 +0000618 StringRef(*cl_include_dir)
Reid Kleckner77b45ba2014-04-23 00:15:01 +0000619 .split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
620 for (StringRef Dir : Dirs)
621 addSystemInclude(DriverArgs, CC1Args, Dir);
622 if (!Dirs.empty())
623 return;
Joao Matos792d7af2012-09-04 17:29:52 +0000624 }
625
Reid Klecknerbf183552017-02-02 19:36:22 +0000626 std::string VSDir;
627
Joao Matos792d7af2012-09-04 17:29:52 +0000628 // When built with access to the proper Windows APIs, try to actually find
629 // the correct include paths first.
Reid Klecknerbf183552017-02-02 19:36:22 +0000630 if (getVisualStudioInstallDir(VSDir)) {
631 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, VSDir, "VC\\include");
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000632
Reid Klecknerbf183552017-02-02 19:36:22 +0000633 if (useUniversalCRT(VSDir)) {
Reid Kleckner7531f7d2015-09-11 00:09:39 +0000634 std::string UniversalCRTSdkPath;
635 std::string UCRTVersion;
636 if (getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion)) {
Igor Kudrinf2e75242015-09-24 05:16:36 +0000637 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath,
638 "Include", UCRTVersion, "ucrt");
Reid Kleckner7531f7d2015-09-11 00:09:39 +0000639 }
640 }
641
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000642 std::string WindowsSDKDir;
Igor Kudrinf2e75242015-09-24 05:16:36 +0000643 int major;
644 std::string windowsSDKIncludeVersion;
645 std::string windowsSDKLibVersion;
646 if (getWindowsSDKDir(WindowsSDKDir, major, windowsSDKIncludeVersion,
647 windowsSDKLibVersion)) {
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000648 if (major >= 8) {
Igor Kudrinf2e75242015-09-24 05:16:36 +0000649 // Note: windowsSDKIncludeVersion is empty for SDKs prior to v10.
650 // Anyway, llvm::sys::path::append is able to manage it.
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000651 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
Igor Kudrinf2e75242015-09-24 05:16:36 +0000652 "include", windowsSDKIncludeVersion,
653 "shared");
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000654 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
Igor Kudrinf2e75242015-09-24 05:16:36 +0000655 "include", windowsSDKIncludeVersion,
656 "um");
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000657 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
Igor Kudrinf2e75242015-09-24 05:16:36 +0000658 "include", windowsSDKIncludeVersion,
659 "winrt");
Zachary Turner0eaf8fc2014-10-22 20:40:28 +0000660 } else {
661 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
662 "include");
663 }
Reid Klecknerbf183552017-02-02 19:36:22 +0000664 } else {
665 addSystemInclude(DriverArgs, CC1Args, VSDir);
Reid Kleckner77b45ba2014-04-23 00:15:01 +0000666 }
Joao Matos792d7af2012-09-04 17:29:52 +0000667 return;
668 }
Joao Matos792d7af2012-09-04 17:29:52 +0000669
David Majnemerd5f7d192016-07-25 04:47:44 +0000670#if defined(LLVM_ON_WIN32)
Joao Matos792d7af2012-09-04 17:29:52 +0000671 // As a fallback, select default install paths.
Alp Tokerfcce1832014-06-22 03:27:45 +0000672 // FIXME: Don't guess drives and paths like this on Windows.
Joao Matos792d7af2012-09-04 17:29:52 +0000673 const StringRef Paths[] = {
674 "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
675 "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
676 "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
677 "C:/Program Files/Microsoft Visual Studio 8/VC/include",
678 "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
679 };
680 addSystemIncludes(DriverArgs, CC1Args, Paths);
David Majnemerd5f7d192016-07-25 04:47:44 +0000681#endif
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000682}
683
Saleem Abdulrasool819f3912014-10-22 02:37:29 +0000684void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
685 ArgStringList &CC1Args) const {
Chandler Carruth1fc603e2011-12-17 23:10:01 +0000686 // FIXME: There should probably be logic here to find libc++ on Windows.
687}
David Majnemere11d3732015-06-08 00:22:46 +0000688
David L. Jones24fb20c2016-12-07 23:41:58 +0000689VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D,
690 const ArgList &Args) const {
691 bool IsWindowsMSVC = getTriple().isWindowsMSVCEnvironment();
692 VersionTuple MSVT = ToolChain::computeMSVCVersion(D, Args);
Reid Klecknerbf183552017-02-02 19:36:22 +0000693 if (MSVT.empty()) MSVT = getMSVCVersionFromTriple();
694 if (MSVT.empty() && IsWindowsMSVC) MSVT = getMSVCVersionFromExe();
David L. Jones24fb20c2016-12-07 23:41:58 +0000695 if (MSVT.empty() &&
696 Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
697 IsWindowsMSVC)) {
698 // -fms-compatibility-version=18.00 is default.
699 // FIXME: Consider bumping this to 19 (MSVC2015) soon.
700 MSVT = VersionTuple(18);
701 }
702 return MSVT;
703}
704
David Majnemere11d3732015-06-08 00:22:46 +0000705std::string
706MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
707 types::ID InputType) const {
David L. Jones24fb20c2016-12-07 23:41:58 +0000708 // The MSVC version doesn't care about the architecture, even though it
709 // may look at the triple internally.
710 VersionTuple MSVT = computeMSVCVersion(/*D=*/nullptr, Args);
David Majnemere11d3732015-06-08 00:22:46 +0000711 MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().getValueOr(0),
712 MSVT.getSubminor().getValueOr(0));
713
David L. Jones24fb20c2016-12-07 23:41:58 +0000714 // For the rest of the triple, however, a computed architecture name may
715 // be needed.
716 llvm::Triple Triple(ToolChain::ComputeEffectiveClangTriple(Args, InputType));
David Majnemer75fdd6b2015-06-09 06:30:01 +0000717 if (Triple.getEnvironment() == llvm::Triple::MSVC) {
718 StringRef ObjFmt = Triple.getEnvironmentName().split('-').second;
719 if (ObjFmt.empty())
720 Triple.setEnvironmentName((Twine("msvc") + MSVT.getAsString()).str());
721 else
722 Triple.setEnvironmentName(
723 (Twine("msvc") + MSVT.getAsString() + Twine('-') + ObjFmt).str());
724 }
David Majnemere11d3732015-06-08 00:22:46 +0000725 return Triple.getTriple();
726}
Alexey Samsonov7f2a0d22015-06-19 21:36:47 +0000727
728SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
729 SanitizerMask Res = ToolChain::getSupportedSanitizers();
730 Res |= SanitizerKind::Address;
Alexey Samsonov7f2a0d22015-06-19 21:36:47 +0000731 return Res;
732}
David Majnemer015ce0f2015-07-27 07:32:11 +0000733
Hans Wennborg21d73d22016-01-12 23:17:03 +0000734static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL,
735 bool SupportsForcingFramePointer,
736 const char *ExpandChar, const OptTable &Opts) {
737 assert(A->getOption().matches(options::OPT__SLASH_O));
738
739 StringRef OptStr = A->getValue();
740 for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
741 const char &OptChar = *(OptStr.data() + I);
742 switch (OptChar) {
743 default:
744 break;
745 case '1':
746 case '2':
747 case 'x':
748 case 'd':
749 if (&OptChar == ExpandChar) {
750 if (OptChar == 'd') {
751 DAL.AddFlagArg(A, Opts.getOption(options::OPT_O0));
752 } else {
753 if (OptChar == '1') {
754 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
755 } else if (OptChar == '2' || OptChar == 'x') {
756 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
757 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
758 }
David Majnemer259d71a2016-01-21 23:01:11 +0000759 if (SupportsForcingFramePointer &&
760 !DAL.hasArgNoClaim(options::OPT_fno_omit_frame_pointer))
Hans Wennborg21d73d22016-01-12 23:17:03 +0000761 DAL.AddFlagArg(A,
762 Opts.getOption(options::OPT_fomit_frame_pointer));
763 if (OptChar == '1' || OptChar == '2')
764 DAL.AddFlagArg(A,
765 Opts.getOption(options::OPT_ffunction_sections));
766 }
767 }
768 break;
769 case 'b':
Hans Wennborg3270bdb2016-05-24 21:23:29 +0000770 if (I + 1 != E && isdigit(OptStr[I + 1])) {
771 switch (OptStr[I + 1]) {
772 case '0':
773 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_inline));
774 break;
775 case '1':
Hans Wennborg44d061a2016-06-22 16:56:16 +0000776 DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_hint_functions));
Hans Wennborg3270bdb2016-05-24 21:23:29 +0000777 break;
778 case '2':
779 DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_functions));
780 break;
781 }
Hans Wennborg21d73d22016-01-12 23:17:03 +0000782 ++I;
Hans Wennborg3270bdb2016-05-24 21:23:29 +0000783 }
Hans Wennborg21d73d22016-01-12 23:17:03 +0000784 break;
785 case 'g':
786 break;
787 case 'i':
788 if (I + 1 != E && OptStr[I + 1] == '-') {
789 ++I;
790 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin));
791 } else {
792 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
793 }
794 break;
795 case 's':
796 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
797 break;
798 case 't':
799 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
800 break;
801 case 'y': {
802 bool OmitFramePointer = true;
803 if (I + 1 != E && OptStr[I + 1] == '-') {
804 OmitFramePointer = false;
805 ++I;
806 }
807 if (SupportsForcingFramePointer) {
808 if (OmitFramePointer)
809 DAL.AddFlagArg(A,
810 Opts.getOption(options::OPT_fomit_frame_pointer));
811 else
812 DAL.AddFlagArg(
813 A, Opts.getOption(options::OPT_fno_omit_frame_pointer));
Nico Weber9c3fca32016-03-23 15:37:41 +0000814 } else {
815 // Don't warn about /Oy- in 64-bit builds (where
816 // SupportsForcingFramePointer is false). The flag having no effect
817 // there is a compiler-internal optimization, and people shouldn't have
818 // to special-case their build files for 64-bit clang-cl.
819 A->claim();
Hans Wennborg21d73d22016-01-12 23:17:03 +0000820 }
821 break;
822 }
823 }
824 }
825}
826
827static void TranslateDArg(Arg *A, llvm::opt::DerivedArgList &DAL,
828 const OptTable &Opts) {
829 assert(A->getOption().matches(options::OPT_D));
830
831 StringRef Val = A->getValue();
832 size_t Hash = Val.find('#');
833 if (Hash == StringRef::npos || Hash > Val.find('=')) {
834 DAL.append(A);
835 return;
836 }
837
838 std::string NewVal = Val;
839 NewVal[Hash] = '=';
840 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_D), NewVal);
841}
842
David Majnemer015ce0f2015-07-27 07:32:11 +0000843llvm::opt::DerivedArgList *
844MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
Samuel Antao31fef982016-10-27 17:39:44 +0000845 StringRef BoundArch, Action::OffloadKind) const {
David Majnemer015ce0f2015-07-27 07:32:11 +0000846 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
847 const OptTable &Opts = getDriver().getOpts();
848
David Majnemer7ab76f22015-08-25 00:46:45 +0000849 // /Oy and /Oy- only has an effect under X86-32.
850 bool SupportsForcingFramePointer = getArch() == llvm::Triple::x86;
851
David Majnemer015ce0f2015-07-27 07:32:11 +0000852 // The -O[12xd] flag actually expands to several flags. We must desugar the
853 // flags so that options embedded can be negated. For example, the '-O2' flag
854 // enables '-Oy'. Expanding '-O2' into its constituent flags allows us to
855 // correctly handle '-O2 -Oy-' where the trailing '-Oy-' disables a single
856 // aspect of '-O2'.
857 //
858 // Note that this expansion logic only applies to the *last* of '[12xd]'.
859
860 // First step is to search for the character we'd like to expand.
861 const char *ExpandChar = nullptr;
862 for (Arg *A : Args) {
863 if (!A->getOption().matches(options::OPT__SLASH_O))
864 continue;
865 StringRef OptStr = A->getValue();
866 for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
Hans Wennborgdebfed92016-05-25 00:43:45 +0000867 char OptChar = OptStr[I];
868 char PrevChar = I > 0 ? OptStr[I - 1] : '0';
869 if (PrevChar == 'b') {
870 // OptChar does not expand; it's an argument to the previous char.
871 continue;
872 }
David Majnemer015ce0f2015-07-27 07:32:11 +0000873 if (OptChar == '1' || OptChar == '2' || OptChar == 'x' || OptChar == 'd')
874 ExpandChar = OptStr.data() + I;
875 }
876 }
877
David Majnemer015ce0f2015-07-27 07:32:11 +0000878 for (Arg *A : Args) {
Hans Wennborg21d73d22016-01-12 23:17:03 +0000879 if (A->getOption().matches(options::OPT__SLASH_O)) {
880 // The -O flag actually takes an amalgam of other options. For example,
881 // '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'.
882 TranslateOptArg(A, *DAL, SupportsForcingFramePointer, ExpandChar, Opts);
883 } else if (A->getOption().matches(options::OPT_D)) {
884 // Translate -Dfoo#bar into -Dfoo=bar.
885 TranslateDArg(A, *DAL, Opts);
886 } else {
David Majnemer015ce0f2015-07-27 07:32:11 +0000887 DAL->append(A);
David Majnemer015ce0f2015-07-27 07:32:11 +0000888 }
889 }
Hans Wennborg21d73d22016-01-12 23:17:03 +0000890
David Majnemer015ce0f2015-07-27 07:32:11 +0000891 return DAL;
892}