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 using namespace clang::driver;
44 using namespace clang::driver::toolchains;
45 using namespace clang::driver::tools;
46 using namespace clang;
47 using namespace llvm::opt;
48
canExecute(llvm::vfs::FileSystem & VFS,StringRef Path)49 static bool canExecute(llvm::vfs::FileSystem &VFS, StringRef Path) {
50 auto Status = VFS.status(Path);
51 if (!Status)
52 return false;
53 return (Status->getPermissions() & llvm::sys::fs::perms::all_exe) != 0;
54 }
55
56 // Try to find Exe from a Visual Studio distribution. This first tries to find
57 // an installed copy of Visual Studio and, failing that, looks in the PATH,
58 // making sure that whatever executable that's found is not a same-named exe
59 // from clang itself to prevent clang from falling back to itself.
FindVisualStudioExecutable(const ToolChain & TC,const char * Exe)60 static std::string FindVisualStudioExecutable(const ToolChain &TC,
61 const char *Exe) {
62 const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC);
63 SmallString<128> FilePath(
64 MSVC.getSubDirectoryPath(llvm::SubDirectoryType::Bin));
65 llvm::sys::path::append(FilePath, Exe);
66 return std::string(canExecute(TC.getVFS(), FilePath) ? FilePath.str() : Exe);
67 }
68
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const69 void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
70 const InputInfo &Output,
71 const InputInfoList &Inputs,
72 const ArgList &Args,
73 const char *LinkingOutput) const {
74 ArgStringList CmdArgs;
75
76 auto &TC = static_cast<const toolchains::MSVCToolChain &>(getToolChain());
77
78 assert((Output.isFilename() || Output.isNothing()) && "invalid output");
79 if (Output.isFilename())
80 CmdArgs.push_back(
81 Args.MakeArgString(std::string("-out:") + Output.getFilename()));
82
83 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) &&
84 !C.getDriver().IsCLMode() && !C.getDriver().IsFlangMode()) {
85 CmdArgs.push_back("-defaultlib:libcmt");
86 CmdArgs.push_back("-defaultlib:oldnames");
87 }
88
89 // If the VC environment hasn't been configured (perhaps because the user
90 // did not run vcvarsall), try to build a consistent link environment. If
91 // the environment variable is set however, assume the user knows what
92 // they're doing. If the user passes /vctoolsdir or /winsdkdir, trust that
93 // over env vars.
94 if (const Arg *A = Args.getLastArg(options::OPT__SLASH_diasdkdir,
95 options::OPT__SLASH_winsysroot)) {
96 // cl.exe doesn't find the DIA SDK automatically, so this too requires
97 // explicit flags and doesn't automatically look in "DIA SDK" relative
98 // to the path we found for VCToolChainPath.
99 llvm::SmallString<128> DIAPath(A->getValue());
100 if (A->getOption().getID() == options::OPT__SLASH_winsysroot)
101 llvm::sys::path::append(DIAPath, "DIA SDK");
102
103 // The DIA SDK always uses the legacy vc arch, even in new MSVC versions.
104 llvm::sys::path::append(DIAPath, "lib",
105 llvm::archToLegacyVCArch(TC.getArch()));
106 CmdArgs.push_back(Args.MakeArgString(Twine("-libpath:") + DIAPath));
107 }
108 if (!llvm::sys::Process::GetEnv("LIB") ||
109 Args.getLastArg(options::OPT__SLASH_vctoolsdir,
110 options::OPT__SLASH_winsysroot)) {
111 CmdArgs.push_back(Args.MakeArgString(
112 Twine("-libpath:") +
113 TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib)));
114 CmdArgs.push_back(Args.MakeArgString(
115 Twine("-libpath:") +
116 TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib, "atlmfc")));
117 }
118 if (!llvm::sys::Process::GetEnv("LIB") ||
119 Args.getLastArg(options::OPT__SLASH_winsdkdir,
120 options::OPT__SLASH_winsysroot)) {
121 if (TC.useUniversalCRT()) {
122 std::string UniversalCRTLibPath;
123 if (TC.getUniversalCRTLibraryPath(Args, UniversalCRTLibPath))
124 CmdArgs.push_back(
125 Args.MakeArgString(Twine("-libpath:") + UniversalCRTLibPath));
126 }
127 std::string WindowsSdkLibPath;
128 if (TC.getWindowsSDKLibraryPath(Args, WindowsSdkLibPath))
129 CmdArgs.push_back(
130 Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath));
131 }
132
133 if (C.getDriver().IsFlangMode()) {
134 addFortranRuntimeLibraryPath(TC, Args, CmdArgs);
135 addFortranRuntimeLibs(TC, CmdArgs);
136
137 // Inform the MSVC linker that we're generating a console application, i.e.
138 // one with `main` as the "user-defined" entry point. The `main` function is
139 // defined in flang's runtime libraries.
140 CmdArgs.push_back("/subsystem:console");
141 }
142
143 // Add the compiler-rt library directories to libpath if they exist to help
144 // the linker find the various sanitizer, builtin, and profiling runtimes.
145 for (const auto &LibPath : TC.getLibraryPaths()) {
146 if (TC.getVFS().exists(LibPath))
147 CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath));
148 }
149 auto CRTPath = TC.getCompilerRTPath();
150 if (TC.getVFS().exists(CRTPath))
151 CmdArgs.push_back(Args.MakeArgString("-libpath:" + CRTPath));
152
153 if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L))
154 for (const auto &LibPath : Args.getAllArgValues(options::OPT_L))
155 CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath));
156
157 CmdArgs.push_back("-nologo");
158
159 if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7))
160 CmdArgs.push_back("-debug");
161
162 // If we specify /hotpatch, let the linker add padding in front of each
163 // function, like MSVC does.
164 if (Args.hasArg(options::OPT_fms_hotpatch, options::OPT__SLASH_hotpatch))
165 CmdArgs.push_back("-functionpadmin");
166
167 // Pass on /Brepro if it was passed to the compiler.
168 // Note that /Brepro maps to -mno-incremental-linker-compatible.
169 bool DefaultIncrementalLinkerCompatible =
170 C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment();
171 if (!Args.hasFlag(options::OPT_mincremental_linker_compatible,
172 options::OPT_mno_incremental_linker_compatible,
173 DefaultIncrementalLinkerCompatible))
174 CmdArgs.push_back("-Brepro");
175
176 bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd,
177 options::OPT_shared);
178 if (DLL) {
179 CmdArgs.push_back(Args.MakeArgString("-dll"));
180
181 SmallString<128> ImplibName(Output.getFilename());
182 llvm::sys::path::replace_extension(ImplibName, "lib");
183 CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName));
184 }
185
186 if (TC.getSanitizerArgs(Args).needsFuzzer()) {
187 if (!Args.hasArg(options::OPT_shared))
188 CmdArgs.push_back(
189 Args.MakeArgString(std::string("-wholearchive:") +
190 TC.getCompilerRTArgString(Args, "fuzzer")));
191 CmdArgs.push_back(Args.MakeArgString("-debug"));
192 // Prevent the linker from padding sections we use for instrumentation
193 // arrays.
194 CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
195 }
196
197 if (TC.getSanitizerArgs(Args).needsAsanRt()) {
198 CmdArgs.push_back(Args.MakeArgString("-debug"));
199 CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
200 if (TC.getSanitizerArgs(Args).needsSharedRt() ||
201 Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
202 for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
203 CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
204 // Make sure the dynamic runtime thunk is not optimized out at link time
205 // to ensure proper SEH handling.
206 CmdArgs.push_back(Args.MakeArgString(
207 TC.getArch() == llvm::Triple::x86
208 ? "-include:___asan_seh_interceptor"
209 : "-include:__asan_seh_interceptor"));
210 // Make sure the linker consider all object files from the dynamic runtime
211 // thunk.
212 CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
213 TC.getCompilerRT(Args, "asan_dynamic_runtime_thunk")));
214 } else if (DLL) {
215 CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
216 } else {
217 for (const auto &Lib : {"asan", "asan_cxx"}) {
218 CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
219 // Make sure the linker consider all object files from the static lib.
220 // This is necessary because instrumented dlls need access to all the
221 // interface exported by the static lib in the main executable.
222 CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
223 TC.getCompilerRT(Args, Lib)));
224 }
225 }
226 }
227
228 Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link);
229
230 // Control Flow Guard checks
231 if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) {
232 StringRef GuardArgs = A->getValue();
233 if (GuardArgs.equals_insensitive("cf") ||
234 GuardArgs.equals_insensitive("cf,nochecks")) {
235 // MSVC doesn't yet support the "nochecks" modifier.
236 CmdArgs.push_back("-guard:cf");
237 } else if (GuardArgs.equals_insensitive("cf-")) {
238 CmdArgs.push_back("-guard:cf-");
239 } else if (GuardArgs.equals_insensitive("ehcont")) {
240 CmdArgs.push_back("-guard:ehcont");
241 } else if (GuardArgs.equals_insensitive("ehcont-")) {
242 CmdArgs.push_back("-guard:ehcont-");
243 }
244 }
245
246 if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
247 options::OPT_fno_openmp, false)) {
248 CmdArgs.push_back("-nodefaultlib:vcomp.lib");
249 CmdArgs.push_back("-nodefaultlib:vcompd.lib");
250 CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
251 TC.getDriver().Dir + "/../lib"));
252 switch (TC.getDriver().getOpenMPRuntime(Args)) {
253 case Driver::OMPRT_OMP:
254 CmdArgs.push_back("-defaultlib:libomp.lib");
255 break;
256 case Driver::OMPRT_IOMP5:
257 CmdArgs.push_back("-defaultlib:libiomp5md.lib");
258 break;
259 case Driver::OMPRT_GOMP:
260 break;
261 case Driver::OMPRT_Unknown:
262 // Already diagnosed.
263 break;
264 }
265 }
266
267 // Add compiler-rt lib in case if it was explicitly
268 // specified as an argument for --rtlib option.
269 if (!Args.hasArg(options::OPT_nostdlib)) {
270 AddRunTimeLibs(TC, TC.getDriver(), CmdArgs, Args);
271 }
272
273 // Add filenames, libraries, and other linker inputs.
274 for (const auto &Input : Inputs) {
275 if (Input.isFilename()) {
276 CmdArgs.push_back(Input.getFilename());
277 continue;
278 }
279
280 const Arg &A = Input.getInputArg();
281
282 // Render -l options differently for the MSVC linker.
283 if (A.getOption().matches(options::OPT_l)) {
284 StringRef Lib = A.getValue();
285 const char *LinkLibArg;
286 if (Lib.endswith(".lib"))
287 LinkLibArg = Args.MakeArgString(Lib);
288 else
289 LinkLibArg = Args.MakeArgString(Lib + ".lib");
290 CmdArgs.push_back(LinkLibArg);
291 continue;
292 }
293
294 // Otherwise, this is some other kind of linker input option like -Wl, -z,
295 // or -L. Render it, even if MSVC doesn't understand it.
296 A.renderAsInput(Args, CmdArgs);
297 }
298
299 addHIPRuntimeLibArgs(TC, Args, CmdArgs);
300
301 TC.addProfileRTLibs(Args, CmdArgs);
302
303 std::vector<const char *> Environment;
304
305 // We need to special case some linker paths. In the case of lld, we need to
306 // translate 'lld' into 'lld-link', and in the case of the regular msvc
307 // linker, we need to use a special search algorithm.
308 llvm::SmallString<128> linkPath;
309 StringRef Linker
310 = Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER);
311 if (Linker.empty())
312 Linker = "link";
313 if (Linker.equals_insensitive("lld"))
314 Linker = "lld-link";
315
316 if (Linker.equals_insensitive("link")) {
317 // If we're using the MSVC linker, it's not sufficient to just use link
318 // from the program PATH, because other environments like GnuWin32 install
319 // their own link.exe which may come first.
320 linkPath = FindVisualStudioExecutable(TC, "link.exe");
321
322 if (!TC.FoundMSVCInstall() && !canExecute(TC.getVFS(), linkPath)) {
323 llvm::SmallString<128> ClPath;
324 ClPath = TC.GetProgramPath("cl.exe");
325 if (canExecute(TC.getVFS(), ClPath)) {
326 linkPath = llvm::sys::path::parent_path(ClPath);
327 llvm::sys::path::append(linkPath, "link.exe");
328 if (!canExecute(TC.getVFS(), linkPath))
329 C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
330 } else {
331 C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
332 }
333 }
334
335 #ifdef _WIN32
336 // When cross-compiling with VS2017 or newer, link.exe expects to have
337 // its containing bin directory at the top of PATH, followed by the
338 // native target bin directory.
339 // e.g. when compiling for x86 on an x64 host, PATH should start with:
340 // /bin/Hostx64/x86;/bin/Hostx64/x64
341 // This doesn't attempt to handle llvm::ToolsetLayout::DevDivInternal.
342 if (TC.getIsVS2017OrNewer() &&
343 llvm::Triple(llvm::sys::getProcessTriple()).getArch() != TC.getArch()) {
344 auto HostArch = llvm::Triple(llvm::sys::getProcessTriple()).getArch();
345
346 auto EnvBlockWide =
347 std::unique_ptr<wchar_t[], decltype(&FreeEnvironmentStringsW)>(
348 GetEnvironmentStringsW(), FreeEnvironmentStringsW);
349 if (!EnvBlockWide)
350 goto SkipSettingEnvironment;
351
352 size_t EnvCount = 0;
353 size_t EnvBlockLen = 0;
354 while (EnvBlockWide[EnvBlockLen] != L'\0') {
355 ++EnvCount;
356 EnvBlockLen += std::wcslen(&EnvBlockWide[EnvBlockLen]) +
357 1 /*string null-terminator*/;
358 }
359 ++EnvBlockLen; // add the block null-terminator
360
361 std::string EnvBlock;
362 if (!llvm::convertUTF16ToUTF8String(
363 llvm::ArrayRef<char>(reinterpret_cast<char *>(EnvBlockWide.get()),
364 EnvBlockLen * sizeof(EnvBlockWide[0])),
365 EnvBlock))
366 goto SkipSettingEnvironment;
367
368 Environment.reserve(EnvCount);
369
370 // Now loop over each string in the block and copy them into the
371 // environment vector, adjusting the PATH variable as needed when we
372 // find it.
373 for (const char *Cursor = EnvBlock.data(); *Cursor != '\0';) {
374 llvm::StringRef EnvVar(Cursor);
375 if (EnvVar.startswith_insensitive("path=")) {
376 constexpr size_t PrefixLen = 5; // strlen("path=")
377 Environment.push_back(Args.MakeArgString(
378 EnvVar.substr(0, PrefixLen) +
379 TC.getSubDirectoryPath(llvm::SubDirectoryType::Bin) +
380 llvm::Twine(llvm::sys::EnvPathSeparator) +
381 TC.getSubDirectoryPath(llvm::SubDirectoryType::Bin, HostArch) +
382 (EnvVar.size() > PrefixLen
383 ? llvm::Twine(llvm::sys::EnvPathSeparator) +
384 EnvVar.substr(PrefixLen)
385 : "")));
386 } else {
387 Environment.push_back(Args.MakeArgString(EnvVar));
388 }
389 Cursor += EnvVar.size() + 1 /*null-terminator*/;
390 }
391 }
392 SkipSettingEnvironment:;
393 #endif
394 } else {
395 linkPath = TC.GetProgramPath(Linker.str().c_str());
396 }
397
398 auto LinkCmd = std::make_unique<Command>(
399 JA, *this, ResponseFileSupport::AtFileUTF16(),
400 Args.MakeArgString(linkPath), CmdArgs, Inputs, Output);
401 if (!Environment.empty())
402 LinkCmd->setEnvironment(Environment);
403 C.addCommand(std::move(LinkCmd));
404 }
405
MSVCToolChain(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)406 MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
407 const ArgList &Args)
408 : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args),
409 RocmInstallation(D, Triple, Args) {
410 getProgramPaths().push_back(getDriver().getInstalledDir());
411 if (getDriver().getInstalledDir() != getDriver().Dir)
412 getProgramPaths().push_back(getDriver().Dir);
413
414 Optional<llvm::StringRef> VCToolsDir, VCToolsVersion;
415 if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir))
416 VCToolsDir = A->getValue();
417 if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsversion))
418 VCToolsVersion = A->getValue();
419 if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkdir))
420 WinSdkDir = A->getValue();
421 if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkversion))
422 WinSdkVersion = A->getValue();
423 if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsysroot))
424 WinSysRoot = A->getValue();
425
426 // Check the command line first, that's the user explicitly telling us what to
427 // use. Check the environment next, in case we're being invoked from a VS
428 // command prompt. Failing that, just try to find the newest Visual Studio
429 // version we can and use its default VC toolchain.
430 llvm::findVCToolChainViaCommandLine(getVFS(), VCToolsDir, VCToolsVersion,
431 WinSysRoot, VCToolChainPath, VSLayout) ||
432 llvm::findVCToolChainViaEnvironment(getVFS(), VCToolChainPath,
433 VSLayout) ||
434 llvm::findVCToolChainViaSetupConfig(getVFS(), VCToolChainPath,
435 VSLayout) ||
436 llvm::findVCToolChainViaRegistry(VCToolChainPath, VSLayout);
437 }
438
buildLinker() const439 Tool *MSVCToolChain::buildLinker() const {
440 return new tools::visualstudio::Linker(*this);
441 }
442
buildAssembler() const443 Tool *MSVCToolChain::buildAssembler() const {
444 if (getTriple().isOSBinFormatMachO())
445 return new tools::darwin::Assembler(*this);
446 getDriver().Diag(clang::diag::err_no_external_assembler);
447 return nullptr;
448 }
449
IsIntegratedAssemblerDefault() const450 bool MSVCToolChain::IsIntegratedAssemblerDefault() const {
451 return true;
452 }
453
IsUnwindTablesDefault(const ArgList & Args) const454 bool MSVCToolChain::IsUnwindTablesDefault(const ArgList &Args) const {
455 // Don't emit unwind tables by default for MachO targets.
456 if (getTriple().isOSBinFormatMachO())
457 return false;
458
459 // All non-x86_32 Windows targets require unwind tables. However, LLVM
460 // doesn't know how to generate them for all targets, so only enable
461 // the ones that are actually implemented.
462 return getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::arm ||
463 getArch() == llvm::Triple::thumb || getArch() == llvm::Triple::aarch64;
464 }
465
isPICDefault() const466 bool MSVCToolChain::isPICDefault() const {
467 return getArch() == llvm::Triple::x86_64 ||
468 getArch() == llvm::Triple::aarch64;
469 }
470
isPIEDefault(const llvm::opt::ArgList & Args) const471 bool MSVCToolChain::isPIEDefault(const llvm::opt::ArgList &Args) const {
472 return false;
473 }
474
isPICDefaultForced() const475 bool MSVCToolChain::isPICDefaultForced() const {
476 return getArch() == llvm::Triple::x86_64 ||
477 getArch() == llvm::Triple::aarch64;
478 }
479
AddCudaIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const480 void MSVCToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
481 ArgStringList &CC1Args) const {
482 CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
483 }
484
AddHIPIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const485 void MSVCToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
486 ArgStringList &CC1Args) const {
487 RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
488 }
489
AddHIPRuntimeLibArgs(const ArgList & Args,ArgStringList & CmdArgs) const490 void MSVCToolChain::AddHIPRuntimeLibArgs(const ArgList &Args,
491 ArgStringList &CmdArgs) const {
492 CmdArgs.append({Args.MakeArgString(StringRef("-libpath:") +
493 RocmInstallation.getLibPath()),
494 "amdhip64.lib"});
495 }
496
printVerboseInfo(raw_ostream & OS) const497 void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const {
498 CudaInstallation.print(OS);
499 RocmInstallation.print(OS);
500 }
501
502 std::string
getSubDirectoryPath(llvm::SubDirectoryType Type,llvm::StringRef SubdirParent) const503 MSVCToolChain::getSubDirectoryPath(llvm::SubDirectoryType Type,
504 llvm::StringRef SubdirParent) const {
505 return llvm::getSubDirectoryPath(Type, VSLayout, VCToolChainPath, getArch(),
506 SubdirParent);
507 }
508
509 std::string
getSubDirectoryPath(llvm::SubDirectoryType Type,llvm::Triple::ArchType TargetArch) const510 MSVCToolChain::getSubDirectoryPath(llvm::SubDirectoryType Type,
511 llvm::Triple::ArchType TargetArch) const {
512 return llvm::getSubDirectoryPath(Type, VSLayout, VCToolChainPath, TargetArch,
513 "");
514 }
515
516 // Find the most recent version of Universal CRT or Windows 10 SDK.
517 // vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include
518 // directory by name and uses the last one of the list.
519 // So we compare entry names lexicographically to find the greatest one.
520 // Gets the library path required to link against the Windows SDK.
getWindowsSDKLibraryPath(const ArgList & Args,std::string & path) const521 bool MSVCToolChain::getWindowsSDKLibraryPath(const ArgList &Args,
522 std::string &path) const {
523 std::string sdkPath;
524 int sdkMajor = 0;
525 std::string windowsSDKIncludeVersion;
526 std::string windowsSDKLibVersion;
527
528 path.clear();
529 if (!llvm::getWindowsSDKDir(getVFS(), WinSdkDir, WinSdkVersion, WinSysRoot,
530 sdkPath, sdkMajor, windowsSDKIncludeVersion,
531 windowsSDKLibVersion))
532 return false;
533
534 llvm::SmallString<128> libPath(sdkPath);
535 llvm::sys::path::append(libPath, "Lib");
536 if (sdkMajor >= 8)
537 llvm::sys::path::append(libPath, windowsSDKLibVersion, "um");
538 return llvm::appendArchToWindowsSDKLibPath(sdkMajor, libPath, getArch(),
539 path);
540 }
541
useUniversalCRT() const542 bool MSVCToolChain::useUniversalCRT() const {
543 return llvm::useUniversalCRT(VSLayout, VCToolChainPath, getArch(), getVFS());
544 }
545
getUniversalCRTLibraryPath(const ArgList & Args,std::string & Path) const546 bool MSVCToolChain::getUniversalCRTLibraryPath(const ArgList &Args,
547 std::string &Path) const {
548 std::string UniversalCRTSdkPath;
549 std::string UCRTVersion;
550
551 Path.clear();
552 if (!llvm::getUniversalCRTSdkDir(getVFS(), WinSdkDir, WinSdkVersion,
553 WinSysRoot, UniversalCRTSdkPath,
554 UCRTVersion))
555 return false;
556
557 StringRef ArchName = llvm::archToWindowsSDKArch(getArch());
558 if (ArchName.empty())
559 return false;
560
561 llvm::SmallString<128> LibPath(UniversalCRTSdkPath);
562 llvm::sys::path::append(LibPath, "Lib", UCRTVersion, "ucrt", ArchName);
563
564 Path = std::string(LibPath.str());
565 return true;
566 }
567
getMSVCVersionFromExe(const std::string & BinDir)568 static VersionTuple getMSVCVersionFromExe(const std::string &BinDir) {
569 VersionTuple Version;
570 #ifdef _WIN32
571 SmallString<128> ClExe(BinDir);
572 llvm::sys::path::append(ClExe, "cl.exe");
573
574 std::wstring ClExeWide;
575 if (!llvm::ConvertUTF8toWide(ClExe.c_str(), ClExeWide))
576 return Version;
577
578 const DWORD VersionSize = ::GetFileVersionInfoSizeW(ClExeWide.c_str(),
579 nullptr);
580 if (VersionSize == 0)
581 return Version;
582
583 SmallVector<uint8_t, 4 * 1024> VersionBlock(VersionSize);
584 if (!::GetFileVersionInfoW(ClExeWide.c_str(), 0, VersionSize,
585 VersionBlock.data()))
586 return Version;
587
588 VS_FIXEDFILEINFO *FileInfo = nullptr;
589 UINT FileInfoSize = 0;
590 if (!::VerQueryValueW(VersionBlock.data(), L"\\",
591 reinterpret_cast<LPVOID *>(&FileInfo), &FileInfoSize) ||
592 FileInfoSize < sizeof(*FileInfo))
593 return Version;
594
595 const unsigned Major = (FileInfo->dwFileVersionMS >> 16) & 0xFFFF;
596 const unsigned Minor = (FileInfo->dwFileVersionMS ) & 0xFFFF;
597 const unsigned Micro = (FileInfo->dwFileVersionLS >> 16) & 0xFFFF;
598
599 Version = VersionTuple(Major, Minor, Micro);
600 #endif
601 return Version;
602 }
603
AddSystemIncludeWithSubfolder(const ArgList & DriverArgs,ArgStringList & CC1Args,const std::string & folder,const Twine & subfolder1,const Twine & subfolder2,const Twine & subfolder3) const604 void MSVCToolChain::AddSystemIncludeWithSubfolder(
605 const ArgList &DriverArgs, ArgStringList &CC1Args,
606 const std::string &folder, const Twine &subfolder1, const Twine &subfolder2,
607 const Twine &subfolder3) const {
608 llvm::SmallString<128> path(folder);
609 llvm::sys::path::append(path, subfolder1, subfolder2, subfolder3);
610 addSystemInclude(DriverArgs, CC1Args, path);
611 }
612
AddClangSystemIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const613 void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
614 ArgStringList &CC1Args) const {
615 if (DriverArgs.hasArg(options::OPT_nostdinc))
616 return;
617
618 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
619 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, getDriver().ResourceDir,
620 "include");
621 }
622
623 // Add %INCLUDE%-like directories from the -imsvc flag.
624 for (const auto &Path : DriverArgs.getAllArgValues(options::OPT__SLASH_imsvc))
625 addSystemInclude(DriverArgs, CC1Args, Path);
626
627 auto AddSystemIncludesFromEnv = [&](StringRef Var) -> bool {
628 if (auto Val = llvm::sys::Process::GetEnv(Var)) {
629 SmallVector<StringRef, 8> Dirs;
630 StringRef(*Val).split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
631 if (!Dirs.empty()) {
632 addSystemIncludes(DriverArgs, CC1Args, Dirs);
633 return true;
634 }
635 }
636 return false;
637 };
638
639 // Add %INCLUDE%-like dirs via /external:env: flags.
640 for (const auto &Var :
641 DriverArgs.getAllArgValues(options::OPT__SLASH_external_env)) {
642 AddSystemIncludesFromEnv(Var);
643 }
644
645 // Add DIA SDK include if requested.
646 if (const Arg *A = DriverArgs.getLastArg(options::OPT__SLASH_diasdkdir,
647 options::OPT__SLASH_winsysroot)) {
648 // cl.exe doesn't find the DIA SDK automatically, so this too requires
649 // explicit flags and doesn't automatically look in "DIA SDK" relative
650 // to the path we found for VCToolChainPath.
651 llvm::SmallString<128> DIASDKPath(A->getValue());
652 if (A->getOption().getID() == options::OPT__SLASH_winsysroot)
653 llvm::sys::path::append(DIASDKPath, "DIA SDK");
654 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, std::string(DIASDKPath),
655 "include");
656 }
657
658 if (DriverArgs.hasArg(options::OPT_nostdlibinc))
659 return;
660
661 // Honor %INCLUDE% and %EXTERNAL_INCLUDE%. It should have essential search
662 // paths set by vcvarsall.bat. Skip if the user expressly set a vctoolsdir.
663 if (!DriverArgs.getLastArg(options::OPT__SLASH_vctoolsdir,
664 options::OPT__SLASH_winsysroot)) {
665 bool Found = AddSystemIncludesFromEnv("INCLUDE");
666 Found |= AddSystemIncludesFromEnv("EXTERNAL_INCLUDE");
667 if (Found)
668 return;
669 }
670
671 // When built with access to the proper Windows APIs, try to actually find
672 // the correct include paths first.
673 if (!VCToolChainPath.empty()) {
674 addSystemInclude(DriverArgs, CC1Args,
675 getSubDirectoryPath(llvm::SubDirectoryType::Include));
676 addSystemInclude(
677 DriverArgs, CC1Args,
678 getSubDirectoryPath(llvm::SubDirectoryType::Include, "atlmfc"));
679
680 if (useUniversalCRT()) {
681 std::string UniversalCRTSdkPath;
682 std::string UCRTVersion;
683 if (llvm::getUniversalCRTSdkDir(getVFS(), WinSdkDir, WinSdkVersion,
684 WinSysRoot, UniversalCRTSdkPath,
685 UCRTVersion)) {
686 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath,
687 "Include", UCRTVersion, "ucrt");
688 }
689 }
690
691 std::string WindowsSDKDir;
692 int major = 0;
693 std::string windowsSDKIncludeVersion;
694 std::string windowsSDKLibVersion;
695 if (llvm::getWindowsSDKDir(getVFS(), WinSdkDir, WinSdkVersion, WinSysRoot,
696 WindowsSDKDir, major, windowsSDKIncludeVersion,
697 windowsSDKLibVersion)) {
698 if (major >= 8) {
699 // Note: windowsSDKIncludeVersion is empty for SDKs prior to v10.
700 // Anyway, llvm::sys::path::append is able to manage it.
701 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
702 "Include", windowsSDKIncludeVersion,
703 "shared");
704 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
705 "Include", windowsSDKIncludeVersion,
706 "um");
707 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
708 "Include", windowsSDKIncludeVersion,
709 "winrt");
710 if (major >= 10) {
711 llvm::VersionTuple Tuple;
712 if (!Tuple.tryParse(windowsSDKIncludeVersion) &&
713 Tuple.getSubminor().value_or(0) >= 17134) {
714 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
715 "Include", windowsSDKIncludeVersion,
716 "cppwinrt");
717 }
718 }
719 } else {
720 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
721 "Include");
722 }
723 }
724
725 return;
726 }
727
728 #if defined(_WIN32)
729 // As a fallback, select default install paths.
730 // FIXME: Don't guess drives and paths like this on Windows.
731 const StringRef Paths[] = {
732 "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
733 "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
734 "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
735 "C:/Program Files/Microsoft Visual Studio 8/VC/include",
736 "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
737 };
738 addSystemIncludes(DriverArgs, CC1Args, Paths);
739 #endif
740 }
741
AddClangCXXStdlibIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const742 void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
743 ArgStringList &CC1Args) const {
744 // FIXME: There should probably be logic here to find libc++ on Windows.
745 }
746
computeMSVCVersion(const Driver * D,const ArgList & Args) const747 VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D,
748 const ArgList &Args) const {
749 bool IsWindowsMSVC = getTriple().isWindowsMSVCEnvironment();
750 VersionTuple MSVT = ToolChain::computeMSVCVersion(D, Args);
751 if (MSVT.empty())
752 MSVT = getTriple().getEnvironmentVersion();
753 if (MSVT.empty() && IsWindowsMSVC)
754 MSVT =
755 getMSVCVersionFromExe(getSubDirectoryPath(llvm::SubDirectoryType::Bin));
756 if (MSVT.empty() &&
757 Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
758 IsWindowsMSVC)) {
759 // -fms-compatibility-version=19.20 is default, aka 2019, 16.x
760 MSVT = VersionTuple(19, 20);
761 }
762 return MSVT;
763 }
764
765 std::string
ComputeEffectiveClangTriple(const ArgList & Args,types::ID InputType) const766 MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
767 types::ID InputType) const {
768 // The MSVC version doesn't care about the architecture, even though it
769 // may look at the triple internally.
770 VersionTuple MSVT = computeMSVCVersion(/*D=*/nullptr, Args);
771 MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().value_or(0),
772 MSVT.getSubminor().value_or(0));
773
774 // For the rest of the triple, however, a computed architecture name may
775 // be needed.
776 llvm::Triple Triple(ToolChain::ComputeEffectiveClangTriple(Args, InputType));
777 if (Triple.getEnvironment() == llvm::Triple::MSVC) {
778 StringRef ObjFmt = Triple.getEnvironmentName().split('-').second;
779 if (ObjFmt.empty())
780 Triple.setEnvironmentName((Twine("msvc") + MSVT.getAsString()).str());
781 else
782 Triple.setEnvironmentName(
783 (Twine("msvc") + MSVT.getAsString() + Twine('-') + ObjFmt).str());
784 }
785 return Triple.getTriple();
786 }
787
getSupportedSanitizers() const788 SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
789 SanitizerMask Res = ToolChain::getSupportedSanitizers();
790 Res |= SanitizerKind::Address;
791 Res |= SanitizerKind::PointerCompare;
792 Res |= SanitizerKind::PointerSubtract;
793 Res |= SanitizerKind::Fuzzer;
794 Res |= SanitizerKind::FuzzerNoLink;
795 Res &= ~SanitizerKind::CFIMFCall;
796 return Res;
797 }
798
TranslateOptArg(Arg * A,llvm::opt::DerivedArgList & DAL,bool SupportsForcingFramePointer,const char * ExpandChar,const OptTable & Opts)799 static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL,
800 bool SupportsForcingFramePointer,
801 const char *ExpandChar, const OptTable &Opts) {
802 assert(A->getOption().matches(options::OPT__SLASH_O));
803
804 StringRef OptStr = A->getValue();
805 for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
806 const char &OptChar = *(OptStr.data() + I);
807 switch (OptChar) {
808 default:
809 break;
810 case '1':
811 case '2':
812 case 'x':
813 case 'd':
814 // Ignore /O[12xd] flags that aren't the last one on the command line.
815 // Only the last one gets expanded.
816 if (&OptChar != ExpandChar) {
817 A->claim();
818 break;
819 }
820 if (OptChar == 'd') {
821 DAL.AddFlagArg(A, Opts.getOption(options::OPT_O0));
822 } else {
823 if (OptChar == '1') {
824 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
825 } else if (OptChar == '2' || OptChar == 'x') {
826 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
827 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
828 }
829 if (SupportsForcingFramePointer &&
830 !DAL.hasArgNoClaim(options::OPT_fno_omit_frame_pointer))
831 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fomit_frame_pointer));
832 if (OptChar == '1' || OptChar == '2')
833 DAL.AddFlagArg(A, Opts.getOption(options::OPT_ffunction_sections));
834 }
835 break;
836 case 'b':
837 if (I + 1 != E && isdigit(OptStr[I + 1])) {
838 switch (OptStr[I + 1]) {
839 case '0':
840 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_inline));
841 break;
842 case '1':
843 DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_hint_functions));
844 break;
845 case '2':
846 DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_functions));
847 break;
848 }
849 ++I;
850 }
851 break;
852 case 'g':
853 A->claim();
854 break;
855 case 'i':
856 if (I + 1 != E && OptStr[I + 1] == '-') {
857 ++I;
858 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin));
859 } else {
860 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
861 }
862 break;
863 case 's':
864 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
865 break;
866 case 't':
867 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
868 break;
869 case 'y': {
870 bool OmitFramePointer = true;
871 if (I + 1 != E && OptStr[I + 1] == '-') {
872 OmitFramePointer = false;
873 ++I;
874 }
875 if (SupportsForcingFramePointer) {
876 if (OmitFramePointer)
877 DAL.AddFlagArg(A,
878 Opts.getOption(options::OPT_fomit_frame_pointer));
879 else
880 DAL.AddFlagArg(
881 A, Opts.getOption(options::OPT_fno_omit_frame_pointer));
882 } else {
883 // Don't warn about /Oy- in x86-64 builds (where
884 // SupportsForcingFramePointer is false). The flag having no effect
885 // there is a compiler-internal optimization, and people shouldn't have
886 // to special-case their build files for x86-64 clang-cl.
887 A->claim();
888 }
889 break;
890 }
891 }
892 }
893 }
894
TranslateDArg(Arg * A,llvm::opt::DerivedArgList & DAL,const OptTable & Opts)895 static void TranslateDArg(Arg *A, llvm::opt::DerivedArgList &DAL,
896 const OptTable &Opts) {
897 assert(A->getOption().matches(options::OPT_D));
898
899 StringRef Val = A->getValue();
900 size_t Hash = Val.find('#');
901 if (Hash == StringRef::npos || Hash > Val.find('=')) {
902 DAL.append(A);
903 return;
904 }
905
906 std::string NewVal = std::string(Val);
907 NewVal[Hash] = '=';
908 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_D), NewVal);
909 }
910
TranslatePermissive(Arg * A,llvm::opt::DerivedArgList & DAL,const OptTable & Opts)911 static void TranslatePermissive(Arg *A, llvm::opt::DerivedArgList &DAL,
912 const OptTable &Opts) {
913 DAL.AddFlagArg(A, Opts.getOption(options::OPT__SLASH_Zc_twoPhase_));
914 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_operator_names));
915 }
916
TranslatePermissiveMinus(Arg * A,llvm::opt::DerivedArgList & DAL,const OptTable & Opts)917 static void TranslatePermissiveMinus(Arg *A, llvm::opt::DerivedArgList &DAL,
918 const OptTable &Opts) {
919 DAL.AddFlagArg(A, Opts.getOption(options::OPT__SLASH_Zc_twoPhase));
920 DAL.AddFlagArg(A, Opts.getOption(options::OPT_foperator_names));
921 }
922
923 llvm::opt::DerivedArgList *
TranslateArgs(const llvm::opt::DerivedArgList & Args,StringRef BoundArch,Action::OffloadKind OFK) const924 MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
925 StringRef BoundArch,
926 Action::OffloadKind OFK) const {
927 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
928 const OptTable &Opts = getDriver().getOpts();
929
930 // /Oy and /Oy- don't have an effect on X86-64
931 bool SupportsForcingFramePointer = getArch() != llvm::Triple::x86_64;
932
933 // The -O[12xd] flag actually expands to several flags. We must desugar the
934 // flags so that options embedded can be negated. For example, the '-O2' flag
935 // enables '-Oy'. Expanding '-O2' into its constituent flags allows us to
936 // correctly handle '-O2 -Oy-' where the trailing '-Oy-' disables a single
937 // aspect of '-O2'.
938 //
939 // Note that this expansion logic only applies to the *last* of '[12xd]'.
940
941 // First step is to search for the character we'd like to expand.
942 const char *ExpandChar = nullptr;
943 for (Arg *A : Args.filtered(options::OPT__SLASH_O)) {
944 StringRef OptStr = A->getValue();
945 for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
946 char OptChar = OptStr[I];
947 char PrevChar = I > 0 ? OptStr[I - 1] : '0';
948 if (PrevChar == 'b') {
949 // OptChar does not expand; it's an argument to the previous char.
950 continue;
951 }
952 if (OptChar == '1' || OptChar == '2' || OptChar == 'x' || OptChar == 'd')
953 ExpandChar = OptStr.data() + I;
954 }
955 }
956
957 for (Arg *A : Args) {
958 if (A->getOption().matches(options::OPT__SLASH_O)) {
959 // The -O flag actually takes an amalgam of other options. For example,
960 // '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'.
961 TranslateOptArg(A, *DAL, SupportsForcingFramePointer, ExpandChar, Opts);
962 } else if (A->getOption().matches(options::OPT_D)) {
963 // Translate -Dfoo#bar into -Dfoo=bar.
964 TranslateDArg(A, *DAL, Opts);
965 } else if (A->getOption().matches(options::OPT__SLASH_permissive)) {
966 // Expand /permissive
967 TranslatePermissive(A, *DAL, Opts);
968 } else if (A->getOption().matches(options::OPT__SLASH_permissive_)) {
969 // Expand /permissive-
970 TranslatePermissiveMinus(A, *DAL, Opts);
971 } else if (OFK != Action::OFK_HIP) {
972 // HIP Toolchain translates input args by itself.
973 DAL->append(A);
974 }
975 }
976
977 return DAL;
978 }
979
addClangTargetOptions(const ArgList & DriverArgs,ArgStringList & CC1Args,Action::OffloadKind DeviceOffloadKind) const980 void MSVCToolChain::addClangTargetOptions(
981 const ArgList &DriverArgs, ArgStringList &CC1Args,
982 Action::OffloadKind DeviceOffloadKind) const {
983 // MSVC STL kindly allows removing all usages of typeid by defining
984 // _HAS_STATIC_RTTI to 0. Do so, when compiling with -fno-rtti
985 if (DriverArgs.hasFlag(options::OPT_fno_rtti, options::OPT_frtti,
986 /*Default=*/false))
987 CC1Args.push_back("-D_HAS_STATIC_RTTI=0");
988 }
989