1 //===-- MSVC.cpp - MSVC ToolChain Implementations -------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "MSVC.h"
10 #include "CommonArgs.h"
11 #include "Darwin.h"
12 #include "clang/Basic/CharInfo.h"
13 #include "clang/Basic/Version.h"
14 #include "clang/Driver/Compilation.h"
15 #include "clang/Driver/Driver.h"
16 #include "clang/Driver/DriverDiagnostic.h"
17 #include "clang/Driver/Options.h"
18 #include "clang/Driver/SanitizerArgs.h"
19 #include "llvm/ADT/StringExtras.h"
20 #include "llvm/ADT/StringSwitch.h"
21 #include "llvm/Option/Arg.h"
22 #include "llvm/Option/ArgList.h"
23 #include "llvm/Support/ConvertUTF.h"
24 #include "llvm/Support/ErrorHandling.h"
25 #include "llvm/Support/FileSystem.h"
26 #include "llvm/Support/Host.h"
27 #include "llvm/Support/MemoryBuffer.h"
28 #include "llvm/Support/Path.h"
29 #include "llvm/Support/Process.h"
30 #include <cstdio>
31
32 #ifdef _WIN32
33 #define WIN32_LEAN_AND_MEAN
34 #define NOGDI
35 #ifndef NOMINMAX
36 #define NOMINMAX
37 #endif
38 #include <windows.h>
39 #endif
40
41 #ifdef _MSC_VER
42 // Don't support SetupApi on MinGW.
43 #define USE_MSVC_SETUP_API
44
45 // Make sure this comes before MSVCSetupApi.h
46 #include <comdef.h>
47
48 #include "MSVCSetupApi.h"
49 #include "llvm/Support/COM.h"
50 _COM_SMARTPTR_TYPEDEF(ISetupConfiguration, __uuidof(ISetupConfiguration));
51 _COM_SMARTPTR_TYPEDEF(ISetupConfiguration2, __uuidof(ISetupConfiguration2));
52 _COM_SMARTPTR_TYPEDEF(ISetupHelper, __uuidof(ISetupHelper));
53 _COM_SMARTPTR_TYPEDEF(IEnumSetupInstances, __uuidof(IEnumSetupInstances));
54 _COM_SMARTPTR_TYPEDEF(ISetupInstance, __uuidof(ISetupInstance));
55 _COM_SMARTPTR_TYPEDEF(ISetupInstance2, __uuidof(ISetupInstance2));
56 #endif
57
58 using namespace clang::driver;
59 using namespace clang::driver::toolchains;
60 using namespace clang::driver::tools;
61 using namespace clang;
62 using namespace llvm::opt;
63
64 // Defined below.
65 // Forward declare this so there aren't too many things above the constructor.
66 static bool getSystemRegistryString(const char *keyPath, const char *valueName,
67 std::string &value, std::string *phValue);
68
69 // Check various environment variables to try and find a toolchain.
findVCToolChainViaEnvironment(std::string & Path,MSVCToolChain::ToolsetLayout & VSLayout)70 static bool findVCToolChainViaEnvironment(std::string &Path,
71 MSVCToolChain::ToolsetLayout &VSLayout) {
72 // These variables are typically set by vcvarsall.bat
73 // when launching a developer command prompt.
74 if (llvm::Optional<std::string> VCToolsInstallDir =
75 llvm::sys::Process::GetEnv("VCToolsInstallDir")) {
76 // This is only set by newer Visual Studios, and it leads straight to
77 // the toolchain directory.
78 Path = std::move(*VCToolsInstallDir);
79 VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
80 return true;
81 }
82 if (llvm::Optional<std::string> VCInstallDir =
83 llvm::sys::Process::GetEnv("VCINSTALLDIR")) {
84 // If the previous variable isn't set but this one is, then we've found
85 // an older Visual Studio. This variable is set by newer Visual Studios too,
86 // so this check has to appear second.
87 // In older Visual Studios, the VC directory is the toolchain.
88 Path = std::move(*VCInstallDir);
89 VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
90 return true;
91 }
92
93 // We couldn't find any VC environment variables. Let's walk through PATH and
94 // see if it leads us to a VC toolchain bin directory. If it does, pick the
95 // first one that we find.
96 if (llvm::Optional<std::string> PathEnv =
97 llvm::sys::Process::GetEnv("PATH")) {
98 llvm::SmallVector<llvm::StringRef, 8> PathEntries;
99 llvm::StringRef(*PathEnv).split(PathEntries, llvm::sys::EnvPathSeparator);
100 for (llvm::StringRef PathEntry : PathEntries) {
101 if (PathEntry.empty())
102 continue;
103
104 llvm::SmallString<256> ExeTestPath;
105
106 // If cl.exe doesn't exist, then this definitely isn't a VC toolchain.
107 ExeTestPath = PathEntry;
108 llvm::sys::path::append(ExeTestPath, "cl.exe");
109 if (!llvm::sys::fs::exists(ExeTestPath))
110 continue;
111
112 // cl.exe existing isn't a conclusive test for a VC toolchain; clang also
113 // has a cl.exe. So let's check for link.exe too.
114 ExeTestPath = PathEntry;
115 llvm::sys::path::append(ExeTestPath, "link.exe");
116 if (!llvm::sys::fs::exists(ExeTestPath))
117 continue;
118
119 // whatever/VC/bin --> old toolchain, VC dir is toolchain dir.
120 llvm::StringRef TestPath = PathEntry;
121 bool IsBin = llvm::sys::path::filename(TestPath).equals_lower("bin");
122 if (!IsBin) {
123 // Strip any architecture subdir like "amd64".
124 TestPath = llvm::sys::path::parent_path(TestPath);
125 IsBin = llvm::sys::path::filename(TestPath).equals_lower("bin");
126 }
127 if (IsBin) {
128 llvm::StringRef ParentPath = llvm::sys::path::parent_path(TestPath);
129 llvm::StringRef ParentFilename = llvm::sys::path::filename(ParentPath);
130 if (ParentFilename == "VC") {
131 Path = ParentPath;
132 VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
133 return true;
134 }
135 if (ParentFilename == "x86ret" || ParentFilename == "x86chk"
136 || ParentFilename == "amd64ret" || ParentFilename == "amd64chk") {
137 Path = ParentPath;
138 VSLayout = MSVCToolChain::ToolsetLayout::DevDivInternal;
139 return true;
140 }
141
142 } else {
143 // This could be a new (>=VS2017) toolchain. If it is, we should find
144 // path components with these prefixes when walking backwards through
145 // the path.
146 // Note: empty strings match anything.
147 llvm::StringRef ExpectedPrefixes[] = {"", "Host", "bin", "",
148 "MSVC", "Tools", "VC"};
149
150 auto It = llvm::sys::path::rbegin(PathEntry);
151 auto End = llvm::sys::path::rend(PathEntry);
152 for (llvm::StringRef Prefix : ExpectedPrefixes) {
153 if (It == End)
154 goto NotAToolChain;
155 if (!It->startswith(Prefix))
156 goto NotAToolChain;
157 ++It;
158 }
159
160 // We've found a new toolchain!
161 // Back up 3 times (/bin/Host/arch) to get the root path.
162 llvm::StringRef ToolChainPath(PathEntry);
163 for (int i = 0; i < 3; ++i)
164 ToolChainPath = llvm::sys::path::parent_path(ToolChainPath);
165
166 Path = ToolChainPath;
167 VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
168 return true;
169 }
170
171 NotAToolChain:
172 continue;
173 }
174 }
175 return false;
176 }
177
178 // Query the Setup Config server for installs, then pick the newest version
179 // and find its default VC toolchain.
180 // This is the preferred way to discover new Visual Studios, as they're no
181 // longer listed in the registry.
findVCToolChainViaSetupConfig(std::string & Path,MSVCToolChain::ToolsetLayout & VSLayout)182 static bool findVCToolChainViaSetupConfig(std::string &Path,
183 MSVCToolChain::ToolsetLayout &VSLayout) {
184 #if !defined(USE_MSVC_SETUP_API)
185 return false;
186 #else
187 // FIXME: This really should be done once in the top-level program's main
188 // function, as it may have already been initialized with a different
189 // threading model otherwise.
190 llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::SingleThreaded);
191 HRESULT HR;
192
193 // _com_ptr_t will throw a _com_error if a COM calls fail.
194 // The LLVM coding standards forbid exception handling, so we'll have to
195 // stop them from being thrown in the first place.
196 // The destructor will put the regular error handler back when we leave
197 // this scope.
198 struct SuppressCOMErrorsRAII {
199 static void __stdcall handler(HRESULT hr, IErrorInfo *perrinfo) {}
200
201 SuppressCOMErrorsRAII() { _set_com_error_handler(handler); }
202
203 ~SuppressCOMErrorsRAII() { _set_com_error_handler(_com_raise_error); }
204
205 } COMErrorSuppressor;
206
207 ISetupConfigurationPtr Query;
208 HR = Query.CreateInstance(__uuidof(SetupConfiguration));
209 if (FAILED(HR))
210 return false;
211
212 IEnumSetupInstancesPtr EnumInstances;
213 HR = ISetupConfiguration2Ptr(Query)->EnumAllInstances(&EnumInstances);
214 if (FAILED(HR))
215 return false;
216
217 ISetupInstancePtr Instance;
218 HR = EnumInstances->Next(1, &Instance, nullptr);
219 if (HR != S_OK)
220 return false;
221
222 ISetupInstancePtr NewestInstance;
223 Optional<uint64_t> NewestVersionNum;
224 do {
225 bstr_t VersionString;
226 uint64_t VersionNum;
227 HR = Instance->GetInstallationVersion(VersionString.GetAddress());
228 if (FAILED(HR))
229 continue;
230 HR = ISetupHelperPtr(Query)->ParseVersion(VersionString, &VersionNum);
231 if (FAILED(HR))
232 continue;
233 if (!NewestVersionNum || (VersionNum > NewestVersionNum)) {
234 NewestInstance = Instance;
235 NewestVersionNum = VersionNum;
236 }
237 } while ((HR = EnumInstances->Next(1, &Instance, nullptr)) == S_OK);
238
239 if (!NewestInstance)
240 return false;
241
242 bstr_t VCPathWide;
243 HR = NewestInstance->ResolvePath(L"VC", VCPathWide.GetAddress());
244 if (FAILED(HR))
245 return false;
246
247 std::string VCRootPath;
248 llvm::convertWideToUTF8(std::wstring(VCPathWide), VCRootPath);
249
250 llvm::SmallString<256> ToolsVersionFilePath(VCRootPath);
251 llvm::sys::path::append(ToolsVersionFilePath, "Auxiliary", "Build",
252 "Microsoft.VCToolsVersion.default.txt");
253
254 auto ToolsVersionFile = llvm::MemoryBuffer::getFile(ToolsVersionFilePath);
255 if (!ToolsVersionFile)
256 return false;
257
258 llvm::SmallString<256> ToolchainPath(VCRootPath);
259 llvm::sys::path::append(ToolchainPath, "Tools", "MSVC",
260 ToolsVersionFile->get()->getBuffer().rtrim());
261 if (!llvm::sys::fs::is_directory(ToolchainPath))
262 return false;
263
264 Path = ToolchainPath.str();
265 VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
266 return true;
267 #endif
268 }
269
270 // Look in the registry for Visual Studio installs, and use that to get
271 // a toolchain path. VS2017 and newer don't get added to the registry.
272 // So if we find something here, we know that it's an older version.
findVCToolChainViaRegistry(std::string & Path,MSVCToolChain::ToolsetLayout & VSLayout)273 static bool findVCToolChainViaRegistry(std::string &Path,
274 MSVCToolChain::ToolsetLayout &VSLayout) {
275 std::string VSInstallPath;
276 if (getSystemRegistryString(R"(SOFTWARE\Microsoft\VisualStudio\$VERSION)",
277 "InstallDir", VSInstallPath, nullptr) ||
278 getSystemRegistryString(R"(SOFTWARE\Microsoft\VCExpress\$VERSION)",
279 "InstallDir", VSInstallPath, nullptr)) {
280 if (!VSInstallPath.empty()) {
281 llvm::SmallString<256> VCPath(llvm::StringRef(
282 VSInstallPath.c_str(), VSInstallPath.find(R"(\Common7\IDE)")));
283 llvm::sys::path::append(VCPath, "VC");
284
285 Path = VCPath.str();
286 VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
287 return true;
288 }
289 }
290 return false;
291 }
292
293 // Try to find Exe from a Visual Studio distribution. This first tries to find
294 // an installed copy of Visual Studio and, failing that, looks in the PATH,
295 // making sure that whatever executable that's found is not a same-named exe
296 // from clang itself to prevent clang from falling back to itself.
FindVisualStudioExecutable(const ToolChain & TC,const char * Exe)297 static std::string FindVisualStudioExecutable(const ToolChain &TC,
298 const char *Exe) {
299 const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC);
300 SmallString<128> FilePath(MSVC.getSubDirectoryPath(
301 toolchains::MSVCToolChain::SubDirectoryType::Bin));
302 llvm::sys::path::append(FilePath, Exe);
303 return llvm::sys::fs::can_execute(FilePath) ? FilePath.str() : Exe;
304 }
305
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const306 void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
307 const InputInfo &Output,
308 const InputInfoList &Inputs,
309 const ArgList &Args,
310 const char *LinkingOutput) const {
311 ArgStringList CmdArgs;
312
313 auto &TC = static_cast<const toolchains::MSVCToolChain &>(getToolChain());
314
315 assert((Output.isFilename() || Output.isNothing()) && "invalid output");
316 if (Output.isFilename())
317 CmdArgs.push_back(
318 Args.MakeArgString(std::string("-out:") + Output.getFilename()));
319
320 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) &&
321 !C.getDriver().IsCLMode())
322 CmdArgs.push_back("-defaultlib:libcmt");
323
324 if (!llvm::sys::Process::GetEnv("LIB")) {
325 // If the VC environment hasn't been configured (perhaps because the user
326 // did not run vcvarsall), try to build a consistent link environment. If
327 // the environment variable is set however, assume the user knows what
328 // they're doing.
329 CmdArgs.push_back(Args.MakeArgString(
330 Twine("-libpath:") +
331 TC.getSubDirectoryPath(
332 toolchains::MSVCToolChain::SubDirectoryType::Lib)));
333
334 if (TC.useUniversalCRT()) {
335 std::string UniversalCRTLibPath;
336 if (TC.getUniversalCRTLibraryPath(UniversalCRTLibPath))
337 CmdArgs.push_back(
338 Args.MakeArgString(Twine("-libpath:") + UniversalCRTLibPath));
339 }
340
341 std::string WindowsSdkLibPath;
342 if (TC.getWindowsSDKLibraryPath(WindowsSdkLibPath))
343 CmdArgs.push_back(
344 Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath));
345 }
346
347 if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L))
348 for (const auto &LibPath : Args.getAllArgValues(options::OPT_L))
349 CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath));
350
351 CmdArgs.push_back("-nologo");
352
353 if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7,
354 options::OPT__SLASH_Zd))
355 CmdArgs.push_back("-debug");
356
357 // Pass on /Brepro if it was passed to the compiler.
358 // Note that /Brepro maps to -mno-incremental-linker-compatible.
359 bool DefaultIncrementalLinkerCompatible =
360 C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment();
361 if (!Args.hasFlag(options::OPT_mincremental_linker_compatible,
362 options::OPT_mno_incremental_linker_compatible,
363 DefaultIncrementalLinkerCompatible))
364 CmdArgs.push_back("-Brepro");
365
366 bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd,
367 options::OPT_shared);
368 if (DLL) {
369 CmdArgs.push_back(Args.MakeArgString("-dll"));
370
371 SmallString<128> ImplibName(Output.getFilename());
372 llvm::sys::path::replace_extension(ImplibName, "lib");
373 CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName));
374 }
375
376 if (TC.getSanitizerArgs().needsFuzzer()) {
377 if (!Args.hasArg(options::OPT_shared))
378 CmdArgs.push_back(
379 Args.MakeArgString(std::string("-wholearchive:") +
380 TC.getCompilerRTArgString(Args, "fuzzer")));
381 CmdArgs.push_back(Args.MakeArgString("-debug"));
382 // Prevent the linker from padding sections we use for instrumentation
383 // arrays.
384 CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
385 }
386
387 if (TC.getSanitizerArgs().needsAsanRt()) {
388 CmdArgs.push_back(Args.MakeArgString("-debug"));
389 CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
390 if (TC.getSanitizerArgs().needsSharedRt() ||
391 Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
392 for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
393 CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
394 // Make sure the dynamic runtime thunk is not optimized out at link time
395 // to ensure proper SEH handling.
396 CmdArgs.push_back(Args.MakeArgString(
397 TC.getArch() == llvm::Triple::x86
398 ? "-include:___asan_seh_interceptor"
399 : "-include:__asan_seh_interceptor"));
400 // Make sure the linker consider all object files from the dynamic runtime
401 // thunk.
402 CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
403 TC.getCompilerRT(Args, "asan_dynamic_runtime_thunk")));
404 } else if (DLL) {
405 CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
406 } else {
407 for (const auto &Lib : {"asan", "asan_cxx"}) {
408 CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
409 // Make sure the linker consider all object files from the static lib.
410 // This is necessary because instrumented dlls need access to all the
411 // interface exported by the static lib in the main executable.
412 CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
413 TC.getCompilerRT(Args, Lib)));
414 }
415 }
416 }
417
418 Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link);
419
420 if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
421 options::OPT_fno_openmp, false)) {
422 CmdArgs.push_back("-nodefaultlib:vcomp.lib");
423 CmdArgs.push_back("-nodefaultlib:vcompd.lib");
424 CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
425 TC.getDriver().Dir + "/../lib"));
426 switch (TC.getDriver().getOpenMPRuntime(Args)) {
427 case Driver::OMPRT_OMP:
428 CmdArgs.push_back("-defaultlib:libomp.lib");
429 break;
430 case Driver::OMPRT_IOMP5:
431 CmdArgs.push_back("-defaultlib:libiomp5md.lib");
432 break;
433 case Driver::OMPRT_GOMP:
434 break;
435 case Driver::OMPRT_Unknown:
436 // Already diagnosed.
437 break;
438 }
439 }
440
441 // Add compiler-rt lib in case if it was explicitly
442 // specified as an argument for --rtlib option.
443 if (!Args.hasArg(options::OPT_nostdlib)) {
444 AddRunTimeLibs(TC, TC.getDriver(), CmdArgs, Args);
445 }
446
447 // Add filenames, libraries, and other linker inputs.
448 for (const auto &Input : Inputs) {
449 if (Input.isFilename()) {
450 CmdArgs.push_back(Input.getFilename());
451 continue;
452 }
453
454 const Arg &A = Input.getInputArg();
455
456 // Render -l options differently for the MSVC linker.
457 if (A.getOption().matches(options::OPT_l)) {
458 StringRef Lib = A.getValue();
459 const char *LinkLibArg;
460 if (Lib.endswith(".lib"))
461 LinkLibArg = Args.MakeArgString(Lib);
462 else
463 LinkLibArg = Args.MakeArgString(Lib + ".lib");
464 CmdArgs.push_back(LinkLibArg);
465 continue;
466 }
467
468 // Otherwise, this is some other kind of linker input option like -Wl, -z,
469 // or -L. Render it, even if MSVC doesn't understand it.
470 A.renderAsInput(Args, CmdArgs);
471 }
472
473 TC.addProfileRTLibs(Args, CmdArgs);
474
475 std::vector<const char *> Environment;
476
477 // We need to special case some linker paths. In the case of lld, we need to
478 // translate 'lld' into 'lld-link', and in the case of the regular msvc
479 // linker, we need to use a special search algorithm.
480 llvm::SmallString<128> linkPath;
481 StringRef Linker = Args.getLastArgValue(options::OPT_fuse_ld_EQ, "link");
482 if (Linker.equals_lower("lld"))
483 Linker = "lld-link";
484
485 if (Linker.equals_lower("link")) {
486 // If we're using the MSVC linker, it's not sufficient to just use link
487 // from the program PATH, because other environments like GnuWin32 install
488 // their own link.exe which may come first.
489 linkPath = FindVisualStudioExecutable(TC, "link.exe");
490
491 if (!TC.FoundMSVCInstall() && !llvm::sys::fs::can_execute(linkPath)) {
492 llvm::SmallString<128> ClPath;
493 ClPath = TC.GetProgramPath("cl.exe");
494 if (llvm::sys::fs::can_execute(ClPath)) {
495 linkPath = llvm::sys::path::parent_path(ClPath);
496 llvm::sys::path::append(linkPath, "link.exe");
497 if (!llvm::sys::fs::can_execute(linkPath))
498 C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
499 } else {
500 C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
501 }
502 }
503
504 #ifdef _WIN32
505 // When cross-compiling with VS2017 or newer, link.exe expects to have
506 // its containing bin directory at the top of PATH, followed by the
507 // native target bin directory.
508 // e.g. when compiling for x86 on an x64 host, PATH should start with:
509 // /bin/Hostx64/x86;/bin/Hostx64/x64
510 // This doesn't attempt to handle ToolsetLayout::DevDivInternal.
511 if (TC.getIsVS2017OrNewer() &&
512 llvm::Triple(llvm::sys::getProcessTriple()).getArch() != TC.getArch()) {
513 auto HostArch = llvm::Triple(llvm::sys::getProcessTriple()).getArch();
514
515 auto EnvBlockWide =
516 std::unique_ptr<wchar_t[], decltype(&FreeEnvironmentStringsW)>(
517 GetEnvironmentStringsW(), FreeEnvironmentStringsW);
518 if (!EnvBlockWide)
519 goto SkipSettingEnvironment;
520
521 size_t EnvCount = 0;
522 size_t EnvBlockLen = 0;
523 while (EnvBlockWide[EnvBlockLen] != L'\0') {
524 ++EnvCount;
525 EnvBlockLen += std::wcslen(&EnvBlockWide[EnvBlockLen]) +
526 1 /*string null-terminator*/;
527 }
528 ++EnvBlockLen; // add the block null-terminator
529
530 std::string EnvBlock;
531 if (!llvm::convertUTF16ToUTF8String(
532 llvm::ArrayRef<char>(reinterpret_cast<char *>(EnvBlockWide.get()),
533 EnvBlockLen * sizeof(EnvBlockWide[0])),
534 EnvBlock))
535 goto SkipSettingEnvironment;
536
537 Environment.reserve(EnvCount);
538
539 // Now loop over each string in the block and copy them into the
540 // environment vector, adjusting the PATH variable as needed when we
541 // find it.
542 for (const char *Cursor = EnvBlock.data(); *Cursor != '\0';) {
543 llvm::StringRef EnvVar(Cursor);
544 if (EnvVar.startswith_lower("path=")) {
545 using SubDirectoryType = toolchains::MSVCToolChain::SubDirectoryType;
546 constexpr size_t PrefixLen = 5; // strlen("path=")
547 Environment.push_back(Args.MakeArgString(
548 EnvVar.substr(0, PrefixLen) +
549 TC.getSubDirectoryPath(SubDirectoryType::Bin) +
550 llvm::Twine(llvm::sys::EnvPathSeparator) +
551 TC.getSubDirectoryPath(SubDirectoryType::Bin, HostArch) +
552 (EnvVar.size() > PrefixLen
553 ? llvm::Twine(llvm::sys::EnvPathSeparator) +
554 EnvVar.substr(PrefixLen)
555 : "")));
556 } else {
557 Environment.push_back(Args.MakeArgString(EnvVar));
558 }
559 Cursor += EnvVar.size() + 1 /*null-terminator*/;
560 }
561 }
562 SkipSettingEnvironment:;
563 #endif
564 } else {
565 linkPath = TC.GetProgramPath(Linker.str().c_str());
566 }
567
568 auto LinkCmd = llvm::make_unique<Command>(
569 JA, *this, Args.MakeArgString(linkPath), CmdArgs, Inputs);
570 if (!Environment.empty())
571 LinkCmd->setEnvironment(Environment);
572 C.addCommand(std::move(LinkCmd));
573 }
574
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const575 void visualstudio::Compiler::ConstructJob(Compilation &C, const JobAction &JA,
576 const InputInfo &Output,
577 const InputInfoList &Inputs,
578 const ArgList &Args,
579 const char *LinkingOutput) const {
580 C.addCommand(GetCommand(C, JA, Output, Inputs, Args, LinkingOutput));
581 }
582
GetCommand(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const583 std::unique_ptr<Command> visualstudio::Compiler::GetCommand(
584 Compilation &C, const JobAction &JA, const InputInfo &Output,
585 const InputInfoList &Inputs, const ArgList &Args,
586 const char *LinkingOutput) const {
587 ArgStringList CmdArgs;
588 CmdArgs.push_back("/nologo");
589 CmdArgs.push_back("/c"); // Compile only.
590 CmdArgs.push_back("/W0"); // No warnings.
591
592 // The goal is to be able to invoke this tool correctly based on
593 // any flag accepted by clang-cl.
594
595 // These are spelled the same way in clang and cl.exe,.
596 Args.AddAllArgs(CmdArgs, {options::OPT_D, options::OPT_U, options::OPT_I});
597
598 // Optimization level.
599 if (Arg *A = Args.getLastArg(options::OPT_fbuiltin, options::OPT_fno_builtin))
600 CmdArgs.push_back(A->getOption().getID() == options::OPT_fbuiltin ? "/Oi"
601 : "/Oi-");
602 if (Arg *A = Args.getLastArg(options::OPT_O, options::OPT_O0)) {
603 if (A->getOption().getID() == options::OPT_O0) {
604 CmdArgs.push_back("/Od");
605 } else {
606 CmdArgs.push_back("/Og");
607
608 StringRef OptLevel = A->getValue();
609 if (OptLevel == "s" || OptLevel == "z")
610 CmdArgs.push_back("/Os");
611 else
612 CmdArgs.push_back("/Ot");
613
614 CmdArgs.push_back("/Ob2");
615 }
616 }
617 if (Arg *A = Args.getLastArg(options::OPT_fomit_frame_pointer,
618 options::OPT_fno_omit_frame_pointer))
619 CmdArgs.push_back(A->getOption().getID() == options::OPT_fomit_frame_pointer
620 ? "/Oy"
621 : "/Oy-");
622 if (!Args.hasArg(options::OPT_fwritable_strings))
623 CmdArgs.push_back("/GF");
624
625 // Flags for which clang-cl has an alias.
626 // FIXME: How can we ensure this stays in sync with relevant clang-cl options?
627
628 if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR,
629 /*Default=*/false))
630 CmdArgs.push_back("/GR-");
631
632 if (Args.hasFlag(options::OPT__SLASH_GS_, options::OPT__SLASH_GS,
633 /*Default=*/false))
634 CmdArgs.push_back("/GS-");
635
636 if (Arg *A = Args.getLastArg(options::OPT_ffunction_sections,
637 options::OPT_fno_function_sections))
638 CmdArgs.push_back(A->getOption().getID() == options::OPT_ffunction_sections
639 ? "/Gy"
640 : "/Gy-");
641 if (Arg *A = Args.getLastArg(options::OPT_fdata_sections,
642 options::OPT_fno_data_sections))
643 CmdArgs.push_back(
644 A->getOption().getID() == options::OPT_fdata_sections ? "/Gw" : "/Gw-");
645 if (Args.hasArg(options::OPT_fsyntax_only))
646 CmdArgs.push_back("/Zs");
647 if (Args.hasArg(options::OPT_g_Flag, options::OPT_gline_tables_only,
648 options::OPT__SLASH_Z7))
649 CmdArgs.push_back("/Z7");
650
651 std::vector<std::string> Includes =
652 Args.getAllArgValues(options::OPT_include);
653 for (const auto &Include : Includes)
654 CmdArgs.push_back(Args.MakeArgString(std::string("/FI") + Include));
655
656 // Flags that can simply be passed through.
657 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LD);
658 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LDd);
659 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_GX);
660 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_GX_);
661 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_EH);
662 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_Zl);
663
664 // The order of these flags is relevant, so pick the last one.
665 if (Arg *A = Args.getLastArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd,
666 options::OPT__SLASH_MT, options::OPT__SLASH_MTd))
667 A->render(Args, CmdArgs);
668
669 // Use MSVC's default threadsafe statics behaviour unless there was a flag.
670 if (Arg *A = Args.getLastArg(options::OPT_fthreadsafe_statics,
671 options::OPT_fno_threadsafe_statics)) {
672 CmdArgs.push_back(A->getOption().getID() == options::OPT_fthreadsafe_statics
673 ? "/Zc:threadSafeInit"
674 : "/Zc:threadSafeInit-");
675 }
676
677 // Pass through all unknown arguments so that the fallback command can see
678 // them too.
679 Args.AddAllArgs(CmdArgs, options::OPT_UNKNOWN);
680
681 // Input filename.
682 assert(Inputs.size() == 1);
683 const InputInfo &II = Inputs[0];
684 assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX);
685 CmdArgs.push_back(II.getType() == types::TY_C ? "/Tc" : "/Tp");
686 if (II.isFilename())
687 CmdArgs.push_back(II.getFilename());
688 else
689 II.getInputArg().renderAsInput(Args, CmdArgs);
690
691 // Output filename.
692 assert(Output.getType() == types::TY_Object);
693 const char *Fo =
694 Args.MakeArgString(std::string("/Fo") + Output.getFilename());
695 CmdArgs.push_back(Fo);
696
697 std::string Exec = FindVisualStudioExecutable(getToolChain(), "cl.exe");
698 return llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
699 CmdArgs, Inputs);
700 }
701
MSVCToolChain(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)702 MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
703 const ArgList &Args)
704 : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args) {
705 getProgramPaths().push_back(getDriver().getInstalledDir());
706 if (getDriver().getInstalledDir() != getDriver().Dir)
707 getProgramPaths().push_back(getDriver().Dir);
708
709 // Check the environment first, since that's probably the user telling us
710 // what they want to use.
711 // Failing that, just try to find the newest Visual Studio version we can
712 // and use its default VC toolchain.
713 findVCToolChainViaEnvironment(VCToolChainPath, VSLayout) ||
714 findVCToolChainViaSetupConfig(VCToolChainPath, VSLayout) ||
715 findVCToolChainViaRegistry(VCToolChainPath, VSLayout);
716 }
717
buildLinker() const718 Tool *MSVCToolChain::buildLinker() const {
719 return new tools::visualstudio::Linker(*this);
720 }
721
buildAssembler() const722 Tool *MSVCToolChain::buildAssembler() const {
723 if (getTriple().isOSBinFormatMachO())
724 return new tools::darwin::Assembler(*this);
725 getDriver().Diag(clang::diag::err_no_external_assembler);
726 return nullptr;
727 }
728
IsIntegratedAssemblerDefault() const729 bool MSVCToolChain::IsIntegratedAssemblerDefault() const {
730 return true;
731 }
732
IsUnwindTablesDefault(const ArgList & Args) const733 bool MSVCToolChain::IsUnwindTablesDefault(const ArgList &Args) const {
734 // Don't emit unwind tables by default for MachO targets.
735 if (getTriple().isOSBinFormatMachO())
736 return false;
737
738 // All non-x86_32 Windows targets require unwind tables. However, LLVM
739 // doesn't know how to generate them for all targets, so only enable
740 // the ones that are actually implemented.
741 return getArch() == llvm::Triple::x86_64 ||
742 getArch() == llvm::Triple::aarch64;
743 }
744
isPICDefault() const745 bool MSVCToolChain::isPICDefault() const {
746 return getArch() == llvm::Triple::x86_64;
747 }
748
isPIEDefault() const749 bool MSVCToolChain::isPIEDefault() const {
750 return false;
751 }
752
isPICDefaultForced() const753 bool MSVCToolChain::isPICDefaultForced() const {
754 return getArch() == llvm::Triple::x86_64;
755 }
756
AddCudaIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const757 void MSVCToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
758 ArgStringList &CC1Args) const {
759 CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
760 }
761
printVerboseInfo(raw_ostream & OS) const762 void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const {
763 CudaInstallation.print(OS);
764 }
765
766 // Windows SDKs and VC Toolchains group their contents into subdirectories based
767 // on the target architecture. This function converts an llvm::Triple::ArchType
768 // to the corresponding subdirectory name.
llvmArchToWindowsSDKArch(llvm::Triple::ArchType Arch)769 static const char *llvmArchToWindowsSDKArch(llvm::Triple::ArchType Arch) {
770 using ArchType = llvm::Triple::ArchType;
771 switch (Arch) {
772 case ArchType::x86:
773 return "x86";
774 case ArchType::x86_64:
775 return "x64";
776 case ArchType::arm:
777 return "arm";
778 case ArchType::aarch64:
779 return "arm64";
780 default:
781 return "";
782 }
783 }
784
785 // Similar to the above function, but for Visual Studios before VS2017.
llvmArchToLegacyVCArch(llvm::Triple::ArchType Arch)786 static const char *llvmArchToLegacyVCArch(llvm::Triple::ArchType Arch) {
787 using ArchType = llvm::Triple::ArchType;
788 switch (Arch) {
789 case ArchType::x86:
790 // x86 is default in legacy VC toolchains.
791 // e.g. x86 libs are directly in /lib as opposed to /lib/x86.
792 return "";
793 case ArchType::x86_64:
794 return "amd64";
795 case ArchType::arm:
796 return "arm";
797 case ArchType::aarch64:
798 return "arm64";
799 default:
800 return "";
801 }
802 }
803
804 // Similar to the above function, but for DevDiv internal builds.
llvmArchToDevDivInternalArch(llvm::Triple::ArchType Arch)805 static const char *llvmArchToDevDivInternalArch(llvm::Triple::ArchType Arch) {
806 using ArchType = llvm::Triple::ArchType;
807 switch (Arch) {
808 case ArchType::x86:
809 return "i386";
810 case ArchType::x86_64:
811 return "amd64";
812 case ArchType::arm:
813 return "arm";
814 case ArchType::aarch64:
815 return "arm64";
816 default:
817 return "";
818 }
819 }
820
821 // Get the path to a specific subdirectory in the current toolchain for
822 // a given target architecture.
823 // VS2017 changed the VC toolchain layout, so this should be used instead
824 // of hardcoding paths.
825 std::string
getSubDirectoryPath(SubDirectoryType Type,llvm::Triple::ArchType TargetArch) const826 MSVCToolChain::getSubDirectoryPath(SubDirectoryType Type,
827 llvm::Triple::ArchType TargetArch) const {
828 const char *SubdirName;
829 const char *IncludeName;
830 switch (VSLayout) {
831 case ToolsetLayout::OlderVS:
832 SubdirName = llvmArchToLegacyVCArch(TargetArch);
833 IncludeName = "include";
834 break;
835 case ToolsetLayout::VS2017OrNewer:
836 SubdirName = llvmArchToWindowsSDKArch(TargetArch);
837 IncludeName = "include";
838 break;
839 case ToolsetLayout::DevDivInternal:
840 SubdirName = llvmArchToDevDivInternalArch(TargetArch);
841 IncludeName = "inc";
842 break;
843 }
844
845 llvm::SmallString<256> Path(VCToolChainPath);
846 switch (Type) {
847 case SubDirectoryType::Bin:
848 if (VSLayout == ToolsetLayout::VS2017OrNewer) {
849 const bool HostIsX64 =
850 llvm::Triple(llvm::sys::getProcessTriple()).isArch64Bit();
851 const char *const HostName = HostIsX64 ? "Hostx64" : "Hostx86";
852 llvm::sys::path::append(Path, "bin", HostName, SubdirName);
853 } else { // OlderVS or DevDivInternal
854 llvm::sys::path::append(Path, "bin", SubdirName);
855 }
856 break;
857 case SubDirectoryType::Include:
858 llvm::sys::path::append(Path, IncludeName);
859 break;
860 case SubDirectoryType::Lib:
861 llvm::sys::path::append(Path, "lib", SubdirName);
862 break;
863 }
864 return Path.str();
865 }
866
867 #ifdef _WIN32
readFullStringValue(HKEY hkey,const char * valueName,std::string & value)868 static bool readFullStringValue(HKEY hkey, const char *valueName,
869 std::string &value) {
870 std::wstring WideValueName;
871 if (!llvm::ConvertUTF8toWide(valueName, WideValueName))
872 return false;
873
874 DWORD result = 0;
875 DWORD valueSize = 0;
876 DWORD type = 0;
877 // First just query for the required size.
878 result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, &type, NULL,
879 &valueSize);
880 if (result != ERROR_SUCCESS || type != REG_SZ || !valueSize)
881 return false;
882 std::vector<BYTE> buffer(valueSize);
883 result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, NULL, &buffer[0],
884 &valueSize);
885 if (result == ERROR_SUCCESS) {
886 std::wstring WideValue(reinterpret_cast<const wchar_t *>(buffer.data()),
887 valueSize / sizeof(wchar_t));
888 if (valueSize && WideValue.back() == L'\0') {
889 WideValue.pop_back();
890 }
891 // The destination buffer must be empty as an invariant of the conversion
892 // function; but this function is sometimes called in a loop that passes in
893 // the same buffer, however. Simply clear it out so we can overwrite it.
894 value.clear();
895 return llvm::convertWideToUTF8(WideValue, value);
896 }
897 return false;
898 }
899 #endif
900
901 /// Read registry string.
902 /// This also supports a means to look for high-versioned keys by use
903 /// of a $VERSION placeholder in the key path.
904 /// $VERSION in the key path is a placeholder for the version number,
905 /// causing the highest value path to be searched for and used.
906 /// I.e. "SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
907 /// There can be additional characters in the component. Only the numeric
908 /// characters are compared. This function only searches HKLM.
getSystemRegistryString(const char * keyPath,const char * valueName,std::string & value,std::string * phValue)909 static bool getSystemRegistryString(const char *keyPath, const char *valueName,
910 std::string &value, std::string *phValue) {
911 #ifndef _WIN32
912 return false;
913 #else
914 HKEY hRootKey = HKEY_LOCAL_MACHINE;
915 HKEY hKey = NULL;
916 long lResult;
917 bool returnValue = false;
918
919 const char *placeHolder = strstr(keyPath, "$VERSION");
920 std::string bestName;
921 // If we have a $VERSION placeholder, do the highest-version search.
922 if (placeHolder) {
923 const char *keyEnd = placeHolder - 1;
924 const char *nextKey = placeHolder;
925 // Find end of previous key.
926 while ((keyEnd > keyPath) && (*keyEnd != '\\'))
927 keyEnd--;
928 // Find end of key containing $VERSION.
929 while (*nextKey && (*nextKey != '\\'))
930 nextKey++;
931 size_t partialKeyLength = keyEnd - keyPath;
932 char partialKey[256];
933 if (partialKeyLength >= sizeof(partialKey))
934 partialKeyLength = sizeof(partialKey) - 1;
935 strncpy(partialKey, keyPath, partialKeyLength);
936 partialKey[partialKeyLength] = '\0';
937 HKEY hTopKey = NULL;
938 lResult = RegOpenKeyExA(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY,
939 &hTopKey);
940 if (lResult == ERROR_SUCCESS) {
941 char keyName[256];
942 double bestValue = 0.0;
943 DWORD index, size = sizeof(keyName) - 1;
944 for (index = 0; RegEnumKeyExA(hTopKey, index, keyName, &size, NULL, NULL,
945 NULL, NULL) == ERROR_SUCCESS;
946 index++) {
947 const char *sp = keyName;
948 while (*sp && !isDigit(*sp))
949 sp++;
950 if (!*sp)
951 continue;
952 const char *ep = sp + 1;
953 while (*ep && (isDigit(*ep) || (*ep == '.')))
954 ep++;
955 char numBuf[32];
956 strncpy(numBuf, sp, sizeof(numBuf) - 1);
957 numBuf[sizeof(numBuf) - 1] = '\0';
958 double dvalue = strtod(numBuf, NULL);
959 if (dvalue > bestValue) {
960 // Test that InstallDir is indeed there before keeping this index.
961 // Open the chosen key path remainder.
962 bestName = keyName;
963 // Append rest of key.
964 bestName.append(nextKey);
965 lResult = RegOpenKeyExA(hTopKey, bestName.c_str(), 0,
966 KEY_READ | KEY_WOW64_32KEY, &hKey);
967 if (lResult == ERROR_SUCCESS) {
968 if (readFullStringValue(hKey, valueName, value)) {
969 bestValue = dvalue;
970 if (phValue)
971 *phValue = bestName;
972 returnValue = true;
973 }
974 RegCloseKey(hKey);
975 }
976 }
977 size = sizeof(keyName) - 1;
978 }
979 RegCloseKey(hTopKey);
980 }
981 } else {
982 lResult =
983 RegOpenKeyExA(hRootKey, keyPath, 0, KEY_READ | KEY_WOW64_32KEY, &hKey);
984 if (lResult == ERROR_SUCCESS) {
985 if (readFullStringValue(hKey, valueName, value))
986 returnValue = true;
987 if (phValue)
988 phValue->clear();
989 RegCloseKey(hKey);
990 }
991 }
992 return returnValue;
993 #endif // _WIN32
994 }
995
996 // Find the most recent version of Universal CRT or Windows 10 SDK.
997 // vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include
998 // directory by name and uses the last one of the list.
999 // So we compare entry names lexicographically to find the greatest one.
getWindows10SDKVersionFromPath(const std::string & SDKPath,std::string & SDKVersion)1000 static bool getWindows10SDKVersionFromPath(const std::string &SDKPath,
1001 std::string &SDKVersion) {
1002 SDKVersion.clear();
1003
1004 std::error_code EC;
1005 llvm::SmallString<128> IncludePath(SDKPath);
1006 llvm::sys::path::append(IncludePath, "Include");
1007 for (llvm::sys::fs::directory_iterator DirIt(IncludePath, EC), DirEnd;
1008 DirIt != DirEnd && !EC; DirIt.increment(EC)) {
1009 if (!llvm::sys::fs::is_directory(DirIt->path()))
1010 continue;
1011 StringRef CandidateName = llvm::sys::path::filename(DirIt->path());
1012 // If WDK is installed, there could be subfolders like "wdf" in the
1013 // "Include" directory.
1014 // Allow only directories which names start with "10.".
1015 if (!CandidateName.startswith("10."))
1016 continue;
1017 if (CandidateName > SDKVersion)
1018 SDKVersion = CandidateName;
1019 }
1020
1021 return !SDKVersion.empty();
1022 }
1023
1024 /// Get Windows SDK installation directory.
getWindowsSDKDir(std::string & Path,int & Major,std::string & WindowsSDKIncludeVersion,std::string & WindowsSDKLibVersion)1025 static bool getWindowsSDKDir(std::string &Path, int &Major,
1026 std::string &WindowsSDKIncludeVersion,
1027 std::string &WindowsSDKLibVersion) {
1028 std::string RegistrySDKVersion;
1029 // Try the Windows registry.
1030 if (!getSystemRegistryString(
1031 "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
1032 "InstallationFolder", Path, &RegistrySDKVersion))
1033 return false;
1034 if (Path.empty() || RegistrySDKVersion.empty())
1035 return false;
1036
1037 WindowsSDKIncludeVersion.clear();
1038 WindowsSDKLibVersion.clear();
1039 Major = 0;
1040 std::sscanf(RegistrySDKVersion.c_str(), "v%d.", &Major);
1041 if (Major <= 7)
1042 return true;
1043 if (Major == 8) {
1044 // Windows SDK 8.x installs libraries in a folder whose names depend on the
1045 // version of the OS you're targeting. By default choose the newest, which
1046 // usually corresponds to the version of the OS you've installed the SDK on.
1047 const char *Tests[] = {"winv6.3", "win8", "win7"};
1048 for (const char *Test : Tests) {
1049 llvm::SmallString<128> TestPath(Path);
1050 llvm::sys::path::append(TestPath, "Lib", Test);
1051 if (llvm::sys::fs::exists(TestPath.c_str())) {
1052 WindowsSDKLibVersion = Test;
1053 break;
1054 }
1055 }
1056 return !WindowsSDKLibVersion.empty();
1057 }
1058 if (Major == 10) {
1059 if (!getWindows10SDKVersionFromPath(Path, WindowsSDKIncludeVersion))
1060 return false;
1061 WindowsSDKLibVersion = WindowsSDKIncludeVersion;
1062 return true;
1063 }
1064 // Unsupported SDK version
1065 return false;
1066 }
1067
1068 // Gets the library path required to link against the Windows SDK.
getWindowsSDKLibraryPath(std::string & path) const1069 bool MSVCToolChain::getWindowsSDKLibraryPath(std::string &path) const {
1070 std::string sdkPath;
1071 int sdkMajor = 0;
1072 std::string windowsSDKIncludeVersion;
1073 std::string windowsSDKLibVersion;
1074
1075 path.clear();
1076 if (!getWindowsSDKDir(sdkPath, sdkMajor, windowsSDKIncludeVersion,
1077 windowsSDKLibVersion))
1078 return false;
1079
1080 llvm::SmallString<128> libPath(sdkPath);
1081 llvm::sys::path::append(libPath, "Lib");
1082 if (sdkMajor >= 8) {
1083 llvm::sys::path::append(libPath, windowsSDKLibVersion, "um",
1084 llvmArchToWindowsSDKArch(getArch()));
1085 } else {
1086 switch (getArch()) {
1087 // In Windows SDK 7.x, x86 libraries are directly in the Lib folder.
1088 case llvm::Triple::x86:
1089 break;
1090 case llvm::Triple::x86_64:
1091 llvm::sys::path::append(libPath, "x64");
1092 break;
1093 case llvm::Triple::arm:
1094 // It is not necessary to link against Windows SDK 7.x when targeting ARM.
1095 return false;
1096 default:
1097 return false;
1098 }
1099 }
1100
1101 path = libPath.str();
1102 return true;
1103 }
1104
1105 // Check if the Include path of a specified version of Visual Studio contains
1106 // specific header files. If not, they are probably shipped with Universal CRT.
useUniversalCRT() const1107 bool MSVCToolChain::useUniversalCRT() const {
1108 llvm::SmallString<128> TestPath(
1109 getSubDirectoryPath(SubDirectoryType::Include));
1110 llvm::sys::path::append(TestPath, "stdlib.h");
1111 return !llvm::sys::fs::exists(TestPath);
1112 }
1113
getUniversalCRTSdkDir(std::string & Path,std::string & UCRTVersion)1114 static bool getUniversalCRTSdkDir(std::string &Path, std::string &UCRTVersion) {
1115 // vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry
1116 // for the specific key "KitsRoot10". So do we.
1117 if (!getSystemRegistryString(
1118 "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10",
1119 Path, nullptr))
1120 return false;
1121
1122 return getWindows10SDKVersionFromPath(Path, UCRTVersion);
1123 }
1124
getUniversalCRTLibraryPath(std::string & Path) const1125 bool MSVCToolChain::getUniversalCRTLibraryPath(std::string &Path) const {
1126 std::string UniversalCRTSdkPath;
1127 std::string UCRTVersion;
1128
1129 Path.clear();
1130 if (!getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion))
1131 return false;
1132
1133 StringRef ArchName = llvmArchToWindowsSDKArch(getArch());
1134 if (ArchName.empty())
1135 return false;
1136
1137 llvm::SmallString<128> LibPath(UniversalCRTSdkPath);
1138 llvm::sys::path::append(LibPath, "Lib", UCRTVersion, "ucrt", ArchName);
1139
1140 Path = LibPath.str();
1141 return true;
1142 }
1143
getMSVCVersionFromTriple(const llvm::Triple & Triple)1144 static VersionTuple getMSVCVersionFromTriple(const llvm::Triple &Triple) {
1145 unsigned Major, Minor, Micro;
1146 Triple.getEnvironmentVersion(Major, Minor, Micro);
1147 if (Major || Minor || Micro)
1148 return VersionTuple(Major, Minor, Micro);
1149 return VersionTuple();
1150 }
1151
getMSVCVersionFromExe(const std::string & BinDir)1152 static VersionTuple getMSVCVersionFromExe(const std::string &BinDir) {
1153 VersionTuple Version;
1154 #ifdef _WIN32
1155 SmallString<128> ClExe(BinDir);
1156 llvm::sys::path::append(ClExe, "cl.exe");
1157
1158 std::wstring ClExeWide;
1159 if (!llvm::ConvertUTF8toWide(ClExe.c_str(), ClExeWide))
1160 return Version;
1161
1162 const DWORD VersionSize = ::GetFileVersionInfoSizeW(ClExeWide.c_str(),
1163 nullptr);
1164 if (VersionSize == 0)
1165 return Version;
1166
1167 SmallVector<uint8_t, 4 * 1024> VersionBlock(VersionSize);
1168 if (!::GetFileVersionInfoW(ClExeWide.c_str(), 0, VersionSize,
1169 VersionBlock.data()))
1170 return Version;
1171
1172 VS_FIXEDFILEINFO *FileInfo = nullptr;
1173 UINT FileInfoSize = 0;
1174 if (!::VerQueryValueW(VersionBlock.data(), L"\\",
1175 reinterpret_cast<LPVOID *>(&FileInfo), &FileInfoSize) ||
1176 FileInfoSize < sizeof(*FileInfo))
1177 return Version;
1178
1179 const unsigned Major = (FileInfo->dwFileVersionMS >> 16) & 0xFFFF;
1180 const unsigned Minor = (FileInfo->dwFileVersionMS ) & 0xFFFF;
1181 const unsigned Micro = (FileInfo->dwFileVersionLS >> 16) & 0xFFFF;
1182
1183 Version = VersionTuple(Major, Minor, Micro);
1184 #endif
1185 return Version;
1186 }
1187
AddSystemIncludeWithSubfolder(const ArgList & DriverArgs,ArgStringList & CC1Args,const std::string & folder,const Twine & subfolder1,const Twine & subfolder2,const Twine & subfolder3) const1188 void MSVCToolChain::AddSystemIncludeWithSubfolder(
1189 const ArgList &DriverArgs, ArgStringList &CC1Args,
1190 const std::string &folder, const Twine &subfolder1, const Twine &subfolder2,
1191 const Twine &subfolder3) const {
1192 llvm::SmallString<128> path(folder);
1193 llvm::sys::path::append(path, subfolder1, subfolder2, subfolder3);
1194 addSystemInclude(DriverArgs, CC1Args, path);
1195 }
1196
AddClangSystemIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const1197 void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
1198 ArgStringList &CC1Args) const {
1199 if (DriverArgs.hasArg(options::OPT_nostdinc))
1200 return;
1201
1202 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
1203 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, getDriver().ResourceDir,
1204 "include");
1205 }
1206
1207 // Add %INCLUDE%-like directories from the -imsvc flag.
1208 for (const auto &Path : DriverArgs.getAllArgValues(options::OPT__SLASH_imsvc))
1209 addSystemInclude(DriverArgs, CC1Args, Path);
1210
1211 if (DriverArgs.hasArg(options::OPT_nostdlibinc))
1212 return;
1213
1214 // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat.
1215 if (llvm::Optional<std::string> cl_include_dir =
1216 llvm::sys::Process::GetEnv("INCLUDE")) {
1217 SmallVector<StringRef, 8> Dirs;
1218 StringRef(*cl_include_dir)
1219 .split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
1220 for (StringRef Dir : Dirs)
1221 addSystemInclude(DriverArgs, CC1Args, Dir);
1222 if (!Dirs.empty())
1223 return;
1224 }
1225
1226 // When built with access to the proper Windows APIs, try to actually find
1227 // the correct include paths first.
1228 if (!VCToolChainPath.empty()) {
1229 addSystemInclude(DriverArgs, CC1Args,
1230 getSubDirectoryPath(SubDirectoryType::Include));
1231
1232 if (useUniversalCRT()) {
1233 std::string UniversalCRTSdkPath;
1234 std::string UCRTVersion;
1235 if (getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion)) {
1236 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath,
1237 "Include", UCRTVersion, "ucrt");
1238 }
1239 }
1240
1241 std::string WindowsSDKDir;
1242 int major;
1243 std::string windowsSDKIncludeVersion;
1244 std::string windowsSDKLibVersion;
1245 if (getWindowsSDKDir(WindowsSDKDir, major, windowsSDKIncludeVersion,
1246 windowsSDKLibVersion)) {
1247 if (major >= 8) {
1248 // Note: windowsSDKIncludeVersion is empty for SDKs prior to v10.
1249 // Anyway, llvm::sys::path::append is able to manage it.
1250 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
1251 "include", windowsSDKIncludeVersion,
1252 "shared");
1253 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
1254 "include", windowsSDKIncludeVersion,
1255 "um");
1256 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
1257 "include", windowsSDKIncludeVersion,
1258 "winrt");
1259 } else {
1260 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
1261 "include");
1262 }
1263 }
1264
1265 return;
1266 }
1267
1268 #if defined(_WIN32)
1269 // As a fallback, select default install paths.
1270 // FIXME: Don't guess drives and paths like this on Windows.
1271 const StringRef Paths[] = {
1272 "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
1273 "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
1274 "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
1275 "C:/Program Files/Microsoft Visual Studio 8/VC/include",
1276 "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
1277 };
1278 addSystemIncludes(DriverArgs, CC1Args, Paths);
1279 #endif
1280 }
1281
AddClangCXXStdlibIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const1282 void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
1283 ArgStringList &CC1Args) const {
1284 // FIXME: There should probably be logic here to find libc++ on Windows.
1285 }
1286
computeMSVCVersion(const Driver * D,const ArgList & Args) const1287 VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D,
1288 const ArgList &Args) const {
1289 bool IsWindowsMSVC = getTriple().isWindowsMSVCEnvironment();
1290 VersionTuple MSVT = ToolChain::computeMSVCVersion(D, Args);
1291 if (MSVT.empty())
1292 MSVT = getMSVCVersionFromTriple(getTriple());
1293 if (MSVT.empty() && IsWindowsMSVC)
1294 MSVT = getMSVCVersionFromExe(getSubDirectoryPath(SubDirectoryType::Bin));
1295 if (MSVT.empty() &&
1296 Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
1297 IsWindowsMSVC)) {
1298 // -fms-compatibility-version=19.11 is default, aka 2017, 15.3
1299 MSVT = VersionTuple(19, 11);
1300 }
1301 return MSVT;
1302 }
1303
1304 std::string
ComputeEffectiveClangTriple(const ArgList & Args,types::ID InputType) const1305 MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
1306 types::ID InputType) const {
1307 // The MSVC version doesn't care about the architecture, even though it
1308 // may look at the triple internally.
1309 VersionTuple MSVT = computeMSVCVersion(/*D=*/nullptr, Args);
1310 MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().getValueOr(0),
1311 MSVT.getSubminor().getValueOr(0));
1312
1313 // For the rest of the triple, however, a computed architecture name may
1314 // be needed.
1315 llvm::Triple Triple(ToolChain::ComputeEffectiveClangTriple(Args, InputType));
1316 if (Triple.getEnvironment() == llvm::Triple::MSVC) {
1317 StringRef ObjFmt = Triple.getEnvironmentName().split('-').second;
1318 if (ObjFmt.empty())
1319 Triple.setEnvironmentName((Twine("msvc") + MSVT.getAsString()).str());
1320 else
1321 Triple.setEnvironmentName(
1322 (Twine("msvc") + MSVT.getAsString() + Twine('-') + ObjFmt).str());
1323 }
1324 return Triple.getTriple();
1325 }
1326
getSupportedSanitizers() const1327 SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
1328 SanitizerMask Res = ToolChain::getSupportedSanitizers();
1329 Res |= SanitizerKind::Address;
1330 Res |= SanitizerKind::PointerCompare;
1331 Res |= SanitizerKind::PointerSubtract;
1332 Res |= SanitizerKind::Fuzzer;
1333 Res |= SanitizerKind::FuzzerNoLink;
1334 Res &= ~SanitizerKind::CFIMFCall;
1335 return Res;
1336 }
1337
TranslateOptArg(Arg * A,llvm::opt::DerivedArgList & DAL,bool SupportsForcingFramePointer,const char * ExpandChar,const OptTable & Opts)1338 static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL,
1339 bool SupportsForcingFramePointer,
1340 const char *ExpandChar, const OptTable &Opts) {
1341 assert(A->getOption().matches(options::OPT__SLASH_O));
1342
1343 StringRef OptStr = A->getValue();
1344 for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
1345 const char &OptChar = *(OptStr.data() + I);
1346 switch (OptChar) {
1347 default:
1348 break;
1349 case '1':
1350 case '2':
1351 case 'x':
1352 case 'd':
1353 // Ignore /O[12xd] flags that aren't the last one on the command line.
1354 // Only the last one gets expanded.
1355 if (&OptChar != ExpandChar) {
1356 A->claim();
1357 break;
1358 }
1359 if (OptChar == 'd') {
1360 DAL.AddFlagArg(A, Opts.getOption(options::OPT_O0));
1361 } else {
1362 if (OptChar == '1') {
1363 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
1364 } else if (OptChar == '2' || OptChar == 'x') {
1365 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
1366 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
1367 }
1368 if (SupportsForcingFramePointer &&
1369 !DAL.hasArgNoClaim(options::OPT_fno_omit_frame_pointer))
1370 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fomit_frame_pointer));
1371 if (OptChar == '1' || OptChar == '2')
1372 DAL.AddFlagArg(A, Opts.getOption(options::OPT_ffunction_sections));
1373 }
1374 break;
1375 case 'b':
1376 if (I + 1 != E && isdigit(OptStr[I + 1])) {
1377 switch (OptStr[I + 1]) {
1378 case '0':
1379 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_inline));
1380 break;
1381 case '1':
1382 DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_hint_functions));
1383 break;
1384 case '2':
1385 DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_functions));
1386 break;
1387 }
1388 ++I;
1389 }
1390 break;
1391 case 'g':
1392 A->claim();
1393 break;
1394 case 'i':
1395 if (I + 1 != E && OptStr[I + 1] == '-') {
1396 ++I;
1397 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin));
1398 } else {
1399 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
1400 }
1401 break;
1402 case 's':
1403 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
1404 break;
1405 case 't':
1406 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
1407 break;
1408 case 'y': {
1409 bool OmitFramePointer = true;
1410 if (I + 1 != E && OptStr[I + 1] == '-') {
1411 OmitFramePointer = false;
1412 ++I;
1413 }
1414 if (SupportsForcingFramePointer) {
1415 if (OmitFramePointer)
1416 DAL.AddFlagArg(A,
1417 Opts.getOption(options::OPT_fomit_frame_pointer));
1418 else
1419 DAL.AddFlagArg(
1420 A, Opts.getOption(options::OPT_fno_omit_frame_pointer));
1421 } else {
1422 // Don't warn about /Oy- in x86-64 builds (where
1423 // SupportsForcingFramePointer is false). The flag having no effect
1424 // there is a compiler-internal optimization, and people shouldn't have
1425 // to special-case their build files for x86-64 clang-cl.
1426 A->claim();
1427 }
1428 break;
1429 }
1430 }
1431 }
1432 }
1433
TranslateDArg(Arg * A,llvm::opt::DerivedArgList & DAL,const OptTable & Opts)1434 static void TranslateDArg(Arg *A, llvm::opt::DerivedArgList &DAL,
1435 const OptTable &Opts) {
1436 assert(A->getOption().matches(options::OPT_D));
1437
1438 StringRef Val = A->getValue();
1439 size_t Hash = Val.find('#');
1440 if (Hash == StringRef::npos || Hash > Val.find('=')) {
1441 DAL.append(A);
1442 return;
1443 }
1444
1445 std::string NewVal = Val;
1446 NewVal[Hash] = '=';
1447 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_D), NewVal);
1448 }
1449
1450 llvm::opt::DerivedArgList *
TranslateArgs(const llvm::opt::DerivedArgList & Args,StringRef BoundArch,Action::OffloadKind) const1451 MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
1452 StringRef BoundArch, Action::OffloadKind) const {
1453 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
1454 const OptTable &Opts = getDriver().getOpts();
1455
1456 // /Oy and /Oy- don't have an effect on X86-64
1457 bool SupportsForcingFramePointer = getArch() != llvm::Triple::x86_64;
1458
1459 // The -O[12xd] flag actually expands to several flags. We must desugar the
1460 // flags so that options embedded can be negated. For example, the '-O2' flag
1461 // enables '-Oy'. Expanding '-O2' into its constituent flags allows us to
1462 // correctly handle '-O2 -Oy-' where the trailing '-Oy-' disables a single
1463 // aspect of '-O2'.
1464 //
1465 // Note that this expansion logic only applies to the *last* of '[12xd]'.
1466
1467 // First step is to search for the character we'd like to expand.
1468 const char *ExpandChar = nullptr;
1469 for (Arg *A : Args.filtered(options::OPT__SLASH_O)) {
1470 StringRef OptStr = A->getValue();
1471 for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
1472 char OptChar = OptStr[I];
1473 char PrevChar = I > 0 ? OptStr[I - 1] : '0';
1474 if (PrevChar == 'b') {
1475 // OptChar does not expand; it's an argument to the previous char.
1476 continue;
1477 }
1478 if (OptChar == '1' || OptChar == '2' || OptChar == 'x' || OptChar == 'd')
1479 ExpandChar = OptStr.data() + I;
1480 }
1481 }
1482
1483 for (Arg *A : Args) {
1484 if (A->getOption().matches(options::OPT__SLASH_O)) {
1485 // The -O flag actually takes an amalgam of other options. For example,
1486 // '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'.
1487 TranslateOptArg(A, *DAL, SupportsForcingFramePointer, ExpandChar, Opts);
1488 } else if (A->getOption().matches(options::OPT_D)) {
1489 // Translate -Dfoo#bar into -Dfoo=bar.
1490 TranslateDArg(A, *DAL, Opts);
1491 } else {
1492 DAL->append(A);
1493 }
1494 }
1495
1496 return DAL;
1497 }
1498