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