10b57cec5SDimitry Andric //===-- MSVC.cpp - MSVC ToolChain Implementations -------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "MSVC.h" 100b57cec5SDimitry Andric #include "CommonArgs.h" 110b57cec5SDimitry Andric #include "Darwin.h" 120b57cec5SDimitry Andric #include "clang/Basic/CharInfo.h" 130b57cec5SDimitry Andric #include "clang/Basic/Version.h" 14d409305fSDimitry Andric #include "clang/Config/config.h" 150b57cec5SDimitry Andric #include "clang/Driver/Compilation.h" 160b57cec5SDimitry Andric #include "clang/Driver/Driver.h" 170b57cec5SDimitry Andric #include "clang/Driver/DriverDiagnostic.h" 180b57cec5SDimitry Andric #include "clang/Driver/Options.h" 190b57cec5SDimitry Andric #include "clang/Driver/SanitizerArgs.h" 200b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 210b57cec5SDimitry Andric #include "llvm/Option/Arg.h" 220b57cec5SDimitry Andric #include "llvm/Option/ArgList.h" 230b57cec5SDimitry Andric #include "llvm/Support/ConvertUTF.h" 240b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 250b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h" 260b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 270b57cec5SDimitry Andric #include "llvm/Support/Path.h" 280b57cec5SDimitry Andric #include "llvm/Support/Process.h" 29fe6060f1SDimitry Andric #include "llvm/Support/VirtualFileSystem.h" 3006c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h" 310b57cec5SDimitry Andric #include <cstdio> 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric #ifdef _WIN32 340b57cec5SDimitry Andric #define WIN32_LEAN_AND_MEAN 350b57cec5SDimitry Andric #define NOGDI 360b57cec5SDimitry Andric #ifndef NOMINMAX 370b57cec5SDimitry Andric #define NOMINMAX 380b57cec5SDimitry Andric #endif 390b57cec5SDimitry Andric #include <windows.h> 400b57cec5SDimitry Andric #endif 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric using namespace clang::driver; 430b57cec5SDimitry Andric using namespace clang::driver::toolchains; 440b57cec5SDimitry Andric using namespace clang::driver::tools; 450b57cec5SDimitry Andric using namespace clang; 460b57cec5SDimitry Andric using namespace llvm::opt; 470b57cec5SDimitry Andric 48fe6060f1SDimitry Andric static bool canExecute(llvm::vfs::FileSystem &VFS, StringRef Path) { 49fe6060f1SDimitry Andric auto Status = VFS.status(Path); 50fe6060f1SDimitry Andric if (!Status) 51fe6060f1SDimitry Andric return false; 52fe6060f1SDimitry Andric return (Status->getPermissions() & llvm::sys::fs::perms::all_exe) != 0; 53fe6060f1SDimitry Andric } 54fe6060f1SDimitry Andric 550b57cec5SDimitry Andric // Try to find Exe from a Visual Studio distribution. This first tries to find 560b57cec5SDimitry Andric // an installed copy of Visual Studio and, failing that, looks in the PATH, 570b57cec5SDimitry Andric // making sure that whatever executable that's found is not a same-named exe 580b57cec5SDimitry Andric // from clang itself to prevent clang from falling back to itself. 590b57cec5SDimitry Andric static std::string FindVisualStudioExecutable(const ToolChain &TC, 600b57cec5SDimitry Andric const char *Exe) { 610b57cec5SDimitry Andric const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC); 6281ad6265SDimitry Andric SmallString<128> FilePath( 6381ad6265SDimitry Andric MSVC.getSubDirectoryPath(llvm::SubDirectoryType::Bin)); 640b57cec5SDimitry Andric llvm::sys::path::append(FilePath, Exe); 65fe6060f1SDimitry Andric return std::string(canExecute(TC.getVFS(), FilePath) ? FilePath.str() : Exe); 660b57cec5SDimitry Andric } 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, 690b57cec5SDimitry Andric const InputInfo &Output, 700b57cec5SDimitry Andric const InputInfoList &Inputs, 710b57cec5SDimitry Andric const ArgList &Args, 720b57cec5SDimitry Andric const char *LinkingOutput) const { 730b57cec5SDimitry Andric ArgStringList CmdArgs; 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric auto &TC = static_cast<const toolchains::MSVCToolChain &>(getToolChain()); 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric assert((Output.isFilename() || Output.isNothing()) && "invalid output"); 780b57cec5SDimitry Andric if (Output.isFilename()) 790b57cec5SDimitry Andric CmdArgs.push_back( 800b57cec5SDimitry Andric Args.MakeArgString(std::string("-out:") + Output.getFilename())); 810b57cec5SDimitry Andric 82*0fca6ea1SDimitry Andric if (Args.hasArg(options::OPT_marm64x)) 83*0fca6ea1SDimitry Andric CmdArgs.push_back("-machine:arm64x"); 84*0fca6ea1SDimitry Andric else if (TC.getTriple().isWindowsArm64EC()) 85*0fca6ea1SDimitry Andric CmdArgs.push_back("-machine:arm64ec"); 86*0fca6ea1SDimitry Andric 870b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) && 8881ad6265SDimitry Andric !C.getDriver().IsCLMode() && !C.getDriver().IsFlangMode()) { 890b57cec5SDimitry Andric CmdArgs.push_back("-defaultlib:libcmt"); 90e8d8bef9SDimitry Andric CmdArgs.push_back("-defaultlib:oldnames"); 91e8d8bef9SDimitry Andric } 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric // If the VC environment hasn't been configured (perhaps because the user 940b57cec5SDimitry Andric // did not run vcvarsall), try to build a consistent link environment. If 950b57cec5SDimitry Andric // the environment variable is set however, assume the user knows what 96fe6060f1SDimitry Andric // they're doing. If the user passes /vctoolsdir or /winsdkdir, trust that 97fe6060f1SDimitry Andric // over env vars. 98349cc55cSDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT__SLASH_diasdkdir, 99349cc55cSDimitry Andric options::OPT__SLASH_winsysroot)) { 100349cc55cSDimitry Andric // cl.exe doesn't find the DIA SDK automatically, so this too requires 101349cc55cSDimitry Andric // explicit flags and doesn't automatically look in "DIA SDK" relative 102349cc55cSDimitry Andric // to the path we found for VCToolChainPath. 103349cc55cSDimitry Andric llvm::SmallString<128> DIAPath(A->getValue()); 104349cc55cSDimitry Andric if (A->getOption().getID() == options::OPT__SLASH_winsysroot) 105349cc55cSDimitry Andric llvm::sys::path::append(DIAPath, "DIA SDK"); 106349cc55cSDimitry Andric 107349cc55cSDimitry Andric // The DIA SDK always uses the legacy vc arch, even in new MSVC versions. 108349cc55cSDimitry Andric llvm::sys::path::append(DIAPath, "lib", 10981ad6265SDimitry Andric llvm::archToLegacyVCArch(TC.getArch())); 110349cc55cSDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine("-libpath:") + DIAPath)); 111349cc55cSDimitry Andric } 112fe6060f1SDimitry Andric if (!llvm::sys::Process::GetEnv("LIB") || 113fe6060f1SDimitry Andric Args.getLastArg(options::OPT__SLASH_vctoolsdir, 114fe6060f1SDimitry Andric options::OPT__SLASH_winsysroot)) { 1150b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString( 1160b57cec5SDimitry Andric Twine("-libpath:") + 11781ad6265SDimitry Andric TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib))); 118a7dea167SDimitry Andric CmdArgs.push_back(Args.MakeArgString( 119a7dea167SDimitry Andric Twine("-libpath:") + 12081ad6265SDimitry Andric TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib, "atlmfc"))); 121fe6060f1SDimitry Andric } 122fe6060f1SDimitry Andric if (!llvm::sys::Process::GetEnv("LIB") || 123fe6060f1SDimitry Andric Args.getLastArg(options::OPT__SLASH_winsdkdir, 124fe6060f1SDimitry Andric options::OPT__SLASH_winsysroot)) { 1250b57cec5SDimitry Andric if (TC.useUniversalCRT()) { 1260b57cec5SDimitry Andric std::string UniversalCRTLibPath; 127fe6060f1SDimitry Andric if (TC.getUniversalCRTLibraryPath(Args, UniversalCRTLibPath)) 1280b57cec5SDimitry Andric CmdArgs.push_back( 1290b57cec5SDimitry Andric Args.MakeArgString(Twine("-libpath:") + UniversalCRTLibPath)); 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric std::string WindowsSdkLibPath; 132fe6060f1SDimitry Andric if (TC.getWindowsSDKLibraryPath(Args, WindowsSdkLibPath)) 1330b57cec5SDimitry Andric CmdArgs.push_back( 1340b57cec5SDimitry Andric Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath)); 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric 137*0fca6ea1SDimitry Andric if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L)) 138*0fca6ea1SDimitry Andric for (const auto &LibPath : Args.getAllArgValues(options::OPT_L)) 139*0fca6ea1SDimitry Andric CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath)); 140*0fca6ea1SDimitry Andric 14181ad6265SDimitry Andric if (C.getDriver().IsFlangMode()) { 14281ad6265SDimitry Andric addFortranRuntimeLibraryPath(TC, Args, CmdArgs); 1435f757f3fSDimitry Andric addFortranRuntimeLibs(TC, Args, CmdArgs); 14481ad6265SDimitry Andric 14581ad6265SDimitry Andric // Inform the MSVC linker that we're generating a console application, i.e. 14681ad6265SDimitry Andric // one with `main` as the "user-defined" entry point. The `main` function is 14781ad6265SDimitry Andric // defined in flang's runtime libraries. 14881ad6265SDimitry Andric CmdArgs.push_back("/subsystem:console"); 14981ad6265SDimitry Andric } 15081ad6265SDimitry Andric 1515ffd83dbSDimitry Andric // Add the compiler-rt library directories to libpath if they exist to help 1525ffd83dbSDimitry Andric // the linker find the various sanitizer, builtin, and profiling runtimes. 1535ffd83dbSDimitry Andric for (const auto &LibPath : TC.getLibraryPaths()) { 1545ffd83dbSDimitry Andric if (TC.getVFS().exists(LibPath)) 1555ffd83dbSDimitry Andric CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath)); 1565ffd83dbSDimitry Andric } 1575ffd83dbSDimitry Andric auto CRTPath = TC.getCompilerRTPath(); 1585ffd83dbSDimitry Andric if (TC.getVFS().exists(CRTPath)) 1595ffd83dbSDimitry Andric CmdArgs.push_back(Args.MakeArgString("-libpath:" + CRTPath)); 1605ffd83dbSDimitry Andric 1610b57cec5SDimitry Andric CmdArgs.push_back("-nologo"); 1620b57cec5SDimitry Andric 163e8d8bef9SDimitry Andric if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7)) 1640b57cec5SDimitry Andric CmdArgs.push_back("-debug"); 1650b57cec5SDimitry Andric 16604eeddc0SDimitry Andric // If we specify /hotpatch, let the linker add padding in front of each 16704eeddc0SDimitry Andric // function, like MSVC does. 16804eeddc0SDimitry Andric if (Args.hasArg(options::OPT_fms_hotpatch, options::OPT__SLASH_hotpatch)) 16904eeddc0SDimitry Andric CmdArgs.push_back("-functionpadmin"); 17004eeddc0SDimitry Andric 1710b57cec5SDimitry Andric // Pass on /Brepro if it was passed to the compiler. 1720b57cec5SDimitry Andric // Note that /Brepro maps to -mno-incremental-linker-compatible. 1730b57cec5SDimitry Andric bool DefaultIncrementalLinkerCompatible = 1740b57cec5SDimitry Andric C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment(); 1750b57cec5SDimitry Andric if (!Args.hasFlag(options::OPT_mincremental_linker_compatible, 1760b57cec5SDimitry Andric options::OPT_mno_incremental_linker_compatible, 1770b57cec5SDimitry Andric DefaultIncrementalLinkerCompatible)) 1780b57cec5SDimitry Andric CmdArgs.push_back("-Brepro"); 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd, 1810b57cec5SDimitry Andric options::OPT_shared); 1820b57cec5SDimitry Andric if (DLL) { 1830b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString("-dll")); 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric SmallString<128> ImplibName(Output.getFilename()); 1860b57cec5SDimitry Andric llvm::sys::path::replace_extension(ImplibName, "lib"); 1870b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName)); 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric 190349cc55cSDimitry Andric if (TC.getSanitizerArgs(Args).needsFuzzer()) { 1910b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_shared)) 1920b57cec5SDimitry Andric CmdArgs.push_back( 1930b57cec5SDimitry Andric Args.MakeArgString(std::string("-wholearchive:") + 1940b57cec5SDimitry Andric TC.getCompilerRTArgString(Args, "fuzzer"))); 1950b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString("-debug")); 1960b57cec5SDimitry Andric // Prevent the linker from padding sections we use for instrumentation 1970b57cec5SDimitry Andric // arrays. 1980b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString("-incremental:no")); 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric 201349cc55cSDimitry Andric if (TC.getSanitizerArgs(Args).needsAsanRt()) { 2020b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString("-debug")); 2030b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString("-incremental:no")); 204349cc55cSDimitry Andric if (TC.getSanitizerArgs(Args).needsSharedRt() || 2050b57cec5SDimitry Andric Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) { 2060b57cec5SDimitry Andric for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"}) 2070b57cec5SDimitry Andric CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib)); 2080b57cec5SDimitry Andric // Make sure the dynamic runtime thunk is not optimized out at link time 2090b57cec5SDimitry Andric // to ensure proper SEH handling. 2100b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString( 2110b57cec5SDimitry Andric TC.getArch() == llvm::Triple::x86 2120b57cec5SDimitry Andric ? "-include:___asan_seh_interceptor" 2130b57cec5SDimitry Andric : "-include:__asan_seh_interceptor")); 2140b57cec5SDimitry Andric // Make sure the linker consider all object files from the dynamic runtime 2150b57cec5SDimitry Andric // thunk. 2160b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") + 2170b57cec5SDimitry Andric TC.getCompilerRT(Args, "asan_dynamic_runtime_thunk"))); 2180b57cec5SDimitry Andric } else if (DLL) { 2190b57cec5SDimitry Andric CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk")); 2200b57cec5SDimitry Andric } else { 2210b57cec5SDimitry Andric for (const auto &Lib : {"asan", "asan_cxx"}) { 2220b57cec5SDimitry Andric CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib)); 2230b57cec5SDimitry Andric // Make sure the linker consider all object files from the static lib. 2240b57cec5SDimitry Andric // This is necessary because instrumented dlls need access to all the 2250b57cec5SDimitry Andric // interface exported by the static lib in the main executable. 2260b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") + 2270b57cec5SDimitry Andric TC.getCompilerRT(Args, Lib))); 2280b57cec5SDimitry Andric } 2290b57cec5SDimitry Andric } 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link); 2330b57cec5SDimitry Andric 234480093f4SDimitry Andric // Control Flow Guard checks 235a324c340SDimitry Andric for (const Arg *A : Args.filtered(options::OPT__SLASH_guard)) { 236480093f4SDimitry Andric StringRef GuardArgs = A->getValue(); 237fe6060f1SDimitry Andric if (GuardArgs.equals_insensitive("cf") || 238fe6060f1SDimitry Andric GuardArgs.equals_insensitive("cf,nochecks")) { 239480093f4SDimitry Andric // MSVC doesn't yet support the "nochecks" modifier. 240480093f4SDimitry Andric CmdArgs.push_back("-guard:cf"); 241fe6060f1SDimitry Andric } else if (GuardArgs.equals_insensitive("cf-")) { 242480093f4SDimitry Andric CmdArgs.push_back("-guard:cf-"); 243fe6060f1SDimitry Andric } else if (GuardArgs.equals_insensitive("ehcont")) { 244fe6060f1SDimitry Andric CmdArgs.push_back("-guard:ehcont"); 245fe6060f1SDimitry Andric } else if (GuardArgs.equals_insensitive("ehcont-")) { 246fe6060f1SDimitry Andric CmdArgs.push_back("-guard:ehcont-"); 247480093f4SDimitry Andric } 248480093f4SDimitry Andric } 249480093f4SDimitry Andric 2500b57cec5SDimitry Andric if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, 2510b57cec5SDimitry Andric options::OPT_fno_openmp, false)) { 2520b57cec5SDimitry Andric CmdArgs.push_back("-nodefaultlib:vcomp.lib"); 2530b57cec5SDimitry Andric CmdArgs.push_back("-nodefaultlib:vcompd.lib"); 2540b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") + 2550b57cec5SDimitry Andric TC.getDriver().Dir + "/../lib")); 2560b57cec5SDimitry Andric switch (TC.getDriver().getOpenMPRuntime(Args)) { 2570b57cec5SDimitry Andric case Driver::OMPRT_OMP: 2580b57cec5SDimitry Andric CmdArgs.push_back("-defaultlib:libomp.lib"); 2590b57cec5SDimitry Andric break; 2600b57cec5SDimitry Andric case Driver::OMPRT_IOMP5: 2610b57cec5SDimitry Andric CmdArgs.push_back("-defaultlib:libiomp5md.lib"); 2620b57cec5SDimitry Andric break; 2630b57cec5SDimitry Andric case Driver::OMPRT_GOMP: 2640b57cec5SDimitry Andric break; 2650b57cec5SDimitry Andric case Driver::OMPRT_Unknown: 2660b57cec5SDimitry Andric // Already diagnosed. 2670b57cec5SDimitry Andric break; 2680b57cec5SDimitry Andric } 2690b57cec5SDimitry Andric } 2700b57cec5SDimitry Andric 2710b57cec5SDimitry Andric // Add compiler-rt lib in case if it was explicitly 2720b57cec5SDimitry Andric // specified as an argument for --rtlib option. 2730b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib)) { 2740b57cec5SDimitry Andric AddRunTimeLibs(TC, TC.getDriver(), CmdArgs, Args); 2750b57cec5SDimitry Andric } 2760b57cec5SDimitry Andric 27706c3fb27SDimitry Andric StringRef Linker = 27806c3fb27SDimitry Andric Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER); 27906c3fb27SDimitry Andric if (Linker.empty()) 28006c3fb27SDimitry Andric Linker = "link"; 28106c3fb27SDimitry Andric // We need to translate 'lld' into 'lld-link'. 28206c3fb27SDimitry Andric else if (Linker.equals_insensitive("lld")) 28306c3fb27SDimitry Andric Linker = "lld-link"; 28406c3fb27SDimitry Andric 28506c3fb27SDimitry Andric if (Linker == "lld-link") { 28606c3fb27SDimitry Andric for (Arg *A : Args.filtered(options::OPT_vfsoverlay)) 28706c3fb27SDimitry Andric CmdArgs.push_back( 28806c3fb27SDimitry Andric Args.MakeArgString(std::string("/vfsoverlay:") + A->getValue())); 28906c3fb27SDimitry Andric 29006c3fb27SDimitry Andric if (C.getDriver().isUsingLTO() && 29106c3fb27SDimitry Andric Args.hasFlag(options::OPT_gsplit_dwarf, options::OPT_gno_split_dwarf, 29206c3fb27SDimitry Andric false)) 29306c3fb27SDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine("/dwodir:") + 29406c3fb27SDimitry Andric Output.getFilename() + "_dwo")); 29506c3fb27SDimitry Andric } 29606c3fb27SDimitry Andric 2970b57cec5SDimitry Andric // Add filenames, libraries, and other linker inputs. 2980b57cec5SDimitry Andric for (const auto &Input : Inputs) { 2990b57cec5SDimitry Andric if (Input.isFilename()) { 3000b57cec5SDimitry Andric CmdArgs.push_back(Input.getFilename()); 3010b57cec5SDimitry Andric continue; 3020b57cec5SDimitry Andric } 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric const Arg &A = Input.getInputArg(); 3050b57cec5SDimitry Andric 3060b57cec5SDimitry Andric // Render -l options differently for the MSVC linker. 3070b57cec5SDimitry Andric if (A.getOption().matches(options::OPT_l)) { 3080b57cec5SDimitry Andric StringRef Lib = A.getValue(); 3090b57cec5SDimitry Andric const char *LinkLibArg; 3105f757f3fSDimitry Andric if (Lib.ends_with(".lib")) 3110b57cec5SDimitry Andric LinkLibArg = Args.MakeArgString(Lib); 3120b57cec5SDimitry Andric else 3130b57cec5SDimitry Andric LinkLibArg = Args.MakeArgString(Lib + ".lib"); 3140b57cec5SDimitry Andric CmdArgs.push_back(LinkLibArg); 3150b57cec5SDimitry Andric continue; 3160b57cec5SDimitry Andric } 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andric // Otherwise, this is some other kind of linker input option like -Wl, -z, 3190b57cec5SDimitry Andric // or -L. Render it, even if MSVC doesn't understand it. 3200b57cec5SDimitry Andric A.renderAsInput(Args, CmdArgs); 3210b57cec5SDimitry Andric } 3220b57cec5SDimitry Andric 3235f757f3fSDimitry Andric addHIPRuntimeLibArgs(TC, C, Args, CmdArgs); 32481ad6265SDimitry Andric 3250b57cec5SDimitry Andric TC.addProfileRTLibs(Args, CmdArgs); 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric std::vector<const char *> Environment; 3280b57cec5SDimitry Andric 32906c3fb27SDimitry Andric // We need to special case some linker paths. In the case of the regular msvc 3300b57cec5SDimitry Andric // linker, we need to use a special search algorithm. 3310b57cec5SDimitry Andric llvm::SmallString<128> linkPath; 332fe6060f1SDimitry Andric if (Linker.equals_insensitive("link")) { 3330b57cec5SDimitry Andric // If we're using the MSVC linker, it's not sufficient to just use link 3340b57cec5SDimitry Andric // from the program PATH, because other environments like GnuWin32 install 3350b57cec5SDimitry Andric // their own link.exe which may come first. 3360b57cec5SDimitry Andric linkPath = FindVisualStudioExecutable(TC, "link.exe"); 3370b57cec5SDimitry Andric 338fe6060f1SDimitry Andric if (!TC.FoundMSVCInstall() && !canExecute(TC.getVFS(), linkPath)) { 3390b57cec5SDimitry Andric llvm::SmallString<128> ClPath; 3400b57cec5SDimitry Andric ClPath = TC.GetProgramPath("cl.exe"); 341fe6060f1SDimitry Andric if (canExecute(TC.getVFS(), ClPath)) { 3420b57cec5SDimitry Andric linkPath = llvm::sys::path::parent_path(ClPath); 3430b57cec5SDimitry Andric llvm::sys::path::append(linkPath, "link.exe"); 344fe6060f1SDimitry Andric if (!canExecute(TC.getVFS(), linkPath)) 3450b57cec5SDimitry Andric C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found); 3460b57cec5SDimitry Andric } else { 3470b57cec5SDimitry Andric C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found); 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric } 3500b57cec5SDimitry Andric 35106c3fb27SDimitry Andric // Clang handles passing the proper asan libs to the linker, which goes 35206c3fb27SDimitry Andric // against link.exe's /INFERASANLIBS which automatically finds asan libs. 35306c3fb27SDimitry Andric if (TC.getSanitizerArgs(Args).needsAsanRt()) 35406c3fb27SDimitry Andric CmdArgs.push_back("/INFERASANLIBS:NO"); 35506c3fb27SDimitry Andric 3560b57cec5SDimitry Andric #ifdef _WIN32 3570b57cec5SDimitry Andric // When cross-compiling with VS2017 or newer, link.exe expects to have 3580b57cec5SDimitry Andric // its containing bin directory at the top of PATH, followed by the 3590b57cec5SDimitry Andric // native target bin directory. 3600b57cec5SDimitry Andric // e.g. when compiling for x86 on an x64 host, PATH should start with: 3610b57cec5SDimitry Andric // /bin/Hostx64/x86;/bin/Hostx64/x64 36281ad6265SDimitry Andric // This doesn't attempt to handle llvm::ToolsetLayout::DevDivInternal. 3630b57cec5SDimitry Andric if (TC.getIsVS2017OrNewer() && 3640b57cec5SDimitry Andric llvm::Triple(llvm::sys::getProcessTriple()).getArch() != TC.getArch()) { 3650b57cec5SDimitry Andric auto HostArch = llvm::Triple(llvm::sys::getProcessTriple()).getArch(); 3660b57cec5SDimitry Andric 3670b57cec5SDimitry Andric auto EnvBlockWide = 3680b57cec5SDimitry Andric std::unique_ptr<wchar_t[], decltype(&FreeEnvironmentStringsW)>( 3690b57cec5SDimitry Andric GetEnvironmentStringsW(), FreeEnvironmentStringsW); 3700b57cec5SDimitry Andric if (!EnvBlockWide) 3710b57cec5SDimitry Andric goto SkipSettingEnvironment; 3720b57cec5SDimitry Andric 3730b57cec5SDimitry Andric size_t EnvCount = 0; 3740b57cec5SDimitry Andric size_t EnvBlockLen = 0; 3750b57cec5SDimitry Andric while (EnvBlockWide[EnvBlockLen] != L'\0') { 3760b57cec5SDimitry Andric ++EnvCount; 3770b57cec5SDimitry Andric EnvBlockLen += std::wcslen(&EnvBlockWide[EnvBlockLen]) + 3780b57cec5SDimitry Andric 1 /*string null-terminator*/; 3790b57cec5SDimitry Andric } 3800b57cec5SDimitry Andric ++EnvBlockLen; // add the block null-terminator 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric std::string EnvBlock; 3830b57cec5SDimitry Andric if (!llvm::convertUTF16ToUTF8String( 3840b57cec5SDimitry Andric llvm::ArrayRef<char>(reinterpret_cast<char *>(EnvBlockWide.get()), 3850b57cec5SDimitry Andric EnvBlockLen * sizeof(EnvBlockWide[0])), 3860b57cec5SDimitry Andric EnvBlock)) 3870b57cec5SDimitry Andric goto SkipSettingEnvironment; 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric Environment.reserve(EnvCount); 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric // Now loop over each string in the block and copy them into the 3920b57cec5SDimitry Andric // environment vector, adjusting the PATH variable as needed when we 3930b57cec5SDimitry Andric // find it. 3940b57cec5SDimitry Andric for (const char *Cursor = EnvBlock.data(); *Cursor != '\0';) { 3950b57cec5SDimitry Andric llvm::StringRef EnvVar(Cursor); 39606c3fb27SDimitry Andric if (EnvVar.starts_with_insensitive("path=")) { 3970b57cec5SDimitry Andric constexpr size_t PrefixLen = 5; // strlen("path=") 3980b57cec5SDimitry Andric Environment.push_back(Args.MakeArgString( 3990b57cec5SDimitry Andric EnvVar.substr(0, PrefixLen) + 40081ad6265SDimitry Andric TC.getSubDirectoryPath(llvm::SubDirectoryType::Bin) + 4010b57cec5SDimitry Andric llvm::Twine(llvm::sys::EnvPathSeparator) + 40281ad6265SDimitry Andric TC.getSubDirectoryPath(llvm::SubDirectoryType::Bin, HostArch) + 4030b57cec5SDimitry Andric (EnvVar.size() > PrefixLen 4040b57cec5SDimitry Andric ? llvm::Twine(llvm::sys::EnvPathSeparator) + 4050b57cec5SDimitry Andric EnvVar.substr(PrefixLen) 4060b57cec5SDimitry Andric : ""))); 4070b57cec5SDimitry Andric } else { 4080b57cec5SDimitry Andric Environment.push_back(Args.MakeArgString(EnvVar)); 4090b57cec5SDimitry Andric } 4100b57cec5SDimitry Andric Cursor += EnvVar.size() + 1 /*null-terminator*/; 4110b57cec5SDimitry Andric } 4120b57cec5SDimitry Andric } 4130b57cec5SDimitry Andric SkipSettingEnvironment:; 4140b57cec5SDimitry Andric #endif 4150b57cec5SDimitry Andric } else { 4160b57cec5SDimitry Andric linkPath = TC.GetProgramPath(Linker.str().c_str()); 4170b57cec5SDimitry Andric } 4180b57cec5SDimitry Andric 419e8d8bef9SDimitry Andric auto LinkCmd = std::make_unique<Command>( 420e8d8bef9SDimitry Andric JA, *this, ResponseFileSupport::AtFileUTF16(), 421e8d8bef9SDimitry Andric Args.MakeArgString(linkPath), CmdArgs, Inputs, Output); 4220b57cec5SDimitry Andric if (!Environment.empty()) 4230b57cec5SDimitry Andric LinkCmd->setEnvironment(Environment); 4240b57cec5SDimitry Andric C.addCommand(std::move(LinkCmd)); 4250b57cec5SDimitry Andric } 4260b57cec5SDimitry Andric 4270b57cec5SDimitry Andric MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple, 4280b57cec5SDimitry Andric const ArgList &Args) 4295ffd83dbSDimitry Andric : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args), 4305ffd83dbSDimitry Andric RocmInstallation(D, Triple, Args) { 4310b57cec5SDimitry Andric getProgramPaths().push_back(getDriver().Dir); 4320b57cec5SDimitry Andric 433bdd1243dSDimitry Andric std::optional<llvm::StringRef> VCToolsDir, VCToolsVersion; 43481ad6265SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir)) 43581ad6265SDimitry Andric VCToolsDir = A->getValue(); 43681ad6265SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsversion)) 43781ad6265SDimitry Andric VCToolsVersion = A->getValue(); 43881ad6265SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkdir)) 43981ad6265SDimitry Andric WinSdkDir = A->getValue(); 44081ad6265SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkversion)) 44181ad6265SDimitry Andric WinSdkVersion = A->getValue(); 44281ad6265SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsysroot)) 44381ad6265SDimitry Andric WinSysRoot = A->getValue(); 44481ad6265SDimitry Andric 445e8d8bef9SDimitry Andric // Check the command line first, that's the user explicitly telling us what to 446e8d8bef9SDimitry Andric // use. Check the environment next, in case we're being invoked from a VS 447e8d8bef9SDimitry Andric // command prompt. Failing that, just try to find the newest Visual Studio 448e8d8bef9SDimitry Andric // version we can and use its default VC toolchain. 44981ad6265SDimitry Andric llvm::findVCToolChainViaCommandLine(getVFS(), VCToolsDir, VCToolsVersion, 45081ad6265SDimitry Andric WinSysRoot, VCToolChainPath, VSLayout) || 45181ad6265SDimitry Andric llvm::findVCToolChainViaEnvironment(getVFS(), VCToolChainPath, 45281ad6265SDimitry Andric VSLayout) || 45306c3fb27SDimitry Andric llvm::findVCToolChainViaSetupConfig(getVFS(), VCToolsVersion, 45406c3fb27SDimitry Andric VCToolChainPath, VSLayout) || 45581ad6265SDimitry Andric llvm::findVCToolChainViaRegistry(VCToolChainPath, VSLayout); 4560b57cec5SDimitry Andric } 4570b57cec5SDimitry Andric 4580b57cec5SDimitry Andric Tool *MSVCToolChain::buildLinker() const { 4590b57cec5SDimitry Andric return new tools::visualstudio::Linker(*this); 4600b57cec5SDimitry Andric } 4610b57cec5SDimitry Andric 4620b57cec5SDimitry Andric Tool *MSVCToolChain::buildAssembler() const { 4630b57cec5SDimitry Andric if (getTriple().isOSBinFormatMachO()) 4640b57cec5SDimitry Andric return new tools::darwin::Assembler(*this); 4650b57cec5SDimitry Andric getDriver().Diag(clang::diag::err_no_external_assembler); 4660b57cec5SDimitry Andric return nullptr; 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric 469bdd1243dSDimitry Andric ToolChain::UnwindTableLevel 470bdd1243dSDimitry Andric MSVCToolChain::getDefaultUnwindTableLevel(const ArgList &Args) const { 4710b57cec5SDimitry Andric // Don't emit unwind tables by default for MachO targets. 4720b57cec5SDimitry Andric if (getTriple().isOSBinFormatMachO()) 473bdd1243dSDimitry Andric return UnwindTableLevel::None; 4740b57cec5SDimitry Andric 4750b57cec5SDimitry Andric // All non-x86_32 Windows targets require unwind tables. However, LLVM 4760b57cec5SDimitry Andric // doesn't know how to generate them for all targets, so only enable 4770b57cec5SDimitry Andric // the ones that are actually implemented. 478bdd1243dSDimitry Andric if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::arm || 479bdd1243dSDimitry Andric getArch() == llvm::Triple::thumb || getArch() == llvm::Triple::aarch64) 480bdd1243dSDimitry Andric return UnwindTableLevel::Asynchronous; 481bdd1243dSDimitry Andric 482bdd1243dSDimitry Andric return UnwindTableLevel::None; 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric bool MSVCToolChain::isPICDefault() const { 486349cc55cSDimitry Andric return getArch() == llvm::Triple::x86_64 || 487349cc55cSDimitry Andric getArch() == llvm::Triple::aarch64; 4880b57cec5SDimitry Andric } 4890b57cec5SDimitry Andric 490349cc55cSDimitry Andric bool MSVCToolChain::isPIEDefault(const llvm::opt::ArgList &Args) const { 4910b57cec5SDimitry Andric return false; 4920b57cec5SDimitry Andric } 4930b57cec5SDimitry Andric 4940b57cec5SDimitry Andric bool MSVCToolChain::isPICDefaultForced() const { 495349cc55cSDimitry Andric return getArch() == llvm::Triple::x86_64 || 496349cc55cSDimitry Andric getArch() == llvm::Triple::aarch64; 4970b57cec5SDimitry Andric } 4980b57cec5SDimitry Andric 4990b57cec5SDimitry Andric void MSVCToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs, 5000b57cec5SDimitry Andric ArgStringList &CC1Args) const { 5017a6dacacSDimitry Andric CudaInstallation->AddCudaIncludeArgs(DriverArgs, CC1Args); 5020b57cec5SDimitry Andric } 5030b57cec5SDimitry Andric 5045ffd83dbSDimitry Andric void MSVCToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs, 5055ffd83dbSDimitry Andric ArgStringList &CC1Args) const { 5067a6dacacSDimitry Andric RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args); 5075ffd83dbSDimitry Andric } 5085ffd83dbSDimitry Andric 50981ad6265SDimitry Andric void MSVCToolChain::AddHIPRuntimeLibArgs(const ArgList &Args, 51081ad6265SDimitry Andric ArgStringList &CmdArgs) const { 51181ad6265SDimitry Andric CmdArgs.append({Args.MakeArgString(StringRef("-libpath:") + 5127a6dacacSDimitry Andric RocmInstallation->getLibPath()), 51381ad6265SDimitry Andric "amdhip64.lib"}); 51481ad6265SDimitry Andric } 51581ad6265SDimitry Andric 5160b57cec5SDimitry Andric void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const { 5177a6dacacSDimitry Andric CudaInstallation->print(OS); 5187a6dacacSDimitry Andric RocmInstallation->print(OS); 5190b57cec5SDimitry Andric } 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric std::string 52281ad6265SDimitry Andric MSVCToolChain::getSubDirectoryPath(llvm::SubDirectoryType Type, 52381ad6265SDimitry Andric llvm::StringRef SubdirParent) const { 52481ad6265SDimitry Andric return llvm::getSubDirectoryPath(Type, VSLayout, VCToolChainPath, getArch(), 52581ad6265SDimitry Andric SubdirParent); 52681ad6265SDimitry Andric } 52781ad6265SDimitry Andric 52881ad6265SDimitry Andric std::string 52981ad6265SDimitry Andric MSVCToolChain::getSubDirectoryPath(llvm::SubDirectoryType Type, 5300b57cec5SDimitry Andric llvm::Triple::ArchType TargetArch) const { 53181ad6265SDimitry Andric return llvm::getSubDirectoryPath(Type, VSLayout, VCToolChainPath, TargetArch, 53281ad6265SDimitry Andric ""); 5330b57cec5SDimitry Andric } 5340b57cec5SDimitry Andric 5350b57cec5SDimitry Andric // Find the most recent version of Universal CRT or Windows 10 SDK. 5360b57cec5SDimitry Andric // vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include 5370b57cec5SDimitry Andric // directory by name and uses the last one of the list. 5380b57cec5SDimitry Andric // So we compare entry names lexicographically to find the greatest one. 5390b57cec5SDimitry Andric // Gets the library path required to link against the Windows SDK. 54081ad6265SDimitry Andric bool MSVCToolChain::getWindowsSDKLibraryPath(const ArgList &Args, 54181ad6265SDimitry Andric std::string &path) const { 5420b57cec5SDimitry Andric std::string sdkPath; 5430b57cec5SDimitry Andric int sdkMajor = 0; 5440b57cec5SDimitry Andric std::string windowsSDKIncludeVersion; 5450b57cec5SDimitry Andric std::string windowsSDKLibVersion; 5460b57cec5SDimitry Andric 5470b57cec5SDimitry Andric path.clear(); 54881ad6265SDimitry Andric if (!llvm::getWindowsSDKDir(getVFS(), WinSdkDir, WinSdkVersion, WinSysRoot, 54981ad6265SDimitry Andric sdkPath, sdkMajor, windowsSDKIncludeVersion, 55081ad6265SDimitry Andric windowsSDKLibVersion)) 5510b57cec5SDimitry Andric return false; 5520b57cec5SDimitry Andric 5530b57cec5SDimitry Andric llvm::SmallString<128> libPath(sdkPath); 5540b57cec5SDimitry Andric llvm::sys::path::append(libPath, "Lib"); 55506c3fb27SDimitry Andric if (sdkMajor >= 10) 55606c3fb27SDimitry Andric if (!(WinSdkDir.has_value() || WinSysRoot.has_value()) && 55706c3fb27SDimitry Andric WinSdkVersion.has_value()) 55806c3fb27SDimitry Andric windowsSDKLibVersion = *WinSdkVersion; 55981ad6265SDimitry Andric if (sdkMajor >= 8) 56081ad6265SDimitry Andric llvm::sys::path::append(libPath, windowsSDKLibVersion, "um"); 56181ad6265SDimitry Andric return llvm::appendArchToWindowsSDKLibPath(sdkMajor, libPath, getArch(), 56281ad6265SDimitry Andric path); 5630b57cec5SDimitry Andric } 5640b57cec5SDimitry Andric 5650b57cec5SDimitry Andric bool MSVCToolChain::useUniversalCRT() const { 56681ad6265SDimitry Andric return llvm::useUniversalCRT(VSLayout, VCToolChainPath, getArch(), getVFS()); 5670b57cec5SDimitry Andric } 5680b57cec5SDimitry Andric 569fe6060f1SDimitry Andric bool MSVCToolChain::getUniversalCRTLibraryPath(const ArgList &Args, 570fe6060f1SDimitry Andric std::string &Path) const { 5710b57cec5SDimitry Andric std::string UniversalCRTSdkPath; 5720b57cec5SDimitry Andric std::string UCRTVersion; 5730b57cec5SDimitry Andric 5740b57cec5SDimitry Andric Path.clear(); 57581ad6265SDimitry Andric if (!llvm::getUniversalCRTSdkDir(getVFS(), WinSdkDir, WinSdkVersion, 57681ad6265SDimitry Andric WinSysRoot, UniversalCRTSdkPath, 57781ad6265SDimitry Andric UCRTVersion)) 5780b57cec5SDimitry Andric return false; 5790b57cec5SDimitry Andric 58006c3fb27SDimitry Andric if (!(WinSdkDir.has_value() || WinSysRoot.has_value()) && 58106c3fb27SDimitry Andric WinSdkVersion.has_value()) 58206c3fb27SDimitry Andric UCRTVersion = *WinSdkVersion; 58306c3fb27SDimitry Andric 58481ad6265SDimitry Andric StringRef ArchName = llvm::archToWindowsSDKArch(getArch()); 5850b57cec5SDimitry Andric if (ArchName.empty()) 5860b57cec5SDimitry Andric return false; 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric llvm::SmallString<128> LibPath(UniversalCRTSdkPath); 5890b57cec5SDimitry Andric llvm::sys::path::append(LibPath, "Lib", UCRTVersion, "ucrt", ArchName); 5900b57cec5SDimitry Andric 5917a6dacacSDimitry Andric Path = std::string(LibPath); 5920b57cec5SDimitry Andric return true; 5930b57cec5SDimitry Andric } 5940b57cec5SDimitry Andric 5950b57cec5SDimitry Andric static VersionTuple getMSVCVersionFromExe(const std::string &BinDir) { 5960b57cec5SDimitry Andric VersionTuple Version; 5970b57cec5SDimitry Andric #ifdef _WIN32 5980b57cec5SDimitry Andric SmallString<128> ClExe(BinDir); 5990b57cec5SDimitry Andric llvm::sys::path::append(ClExe, "cl.exe"); 6000b57cec5SDimitry Andric 6010b57cec5SDimitry Andric std::wstring ClExeWide; 6020b57cec5SDimitry Andric if (!llvm::ConvertUTF8toWide(ClExe.c_str(), ClExeWide)) 6030b57cec5SDimitry Andric return Version; 6040b57cec5SDimitry Andric 6050b57cec5SDimitry Andric const DWORD VersionSize = ::GetFileVersionInfoSizeW(ClExeWide.c_str(), 6060b57cec5SDimitry Andric nullptr); 6070b57cec5SDimitry Andric if (VersionSize == 0) 6080b57cec5SDimitry Andric return Version; 6090b57cec5SDimitry Andric 6100b57cec5SDimitry Andric SmallVector<uint8_t, 4 * 1024> VersionBlock(VersionSize); 6110b57cec5SDimitry Andric if (!::GetFileVersionInfoW(ClExeWide.c_str(), 0, VersionSize, 6120b57cec5SDimitry Andric VersionBlock.data())) 6130b57cec5SDimitry Andric return Version; 6140b57cec5SDimitry Andric 6150b57cec5SDimitry Andric VS_FIXEDFILEINFO *FileInfo = nullptr; 6160b57cec5SDimitry Andric UINT FileInfoSize = 0; 6170b57cec5SDimitry Andric if (!::VerQueryValueW(VersionBlock.data(), L"\\", 6180b57cec5SDimitry Andric reinterpret_cast<LPVOID *>(&FileInfo), &FileInfoSize) || 6190b57cec5SDimitry Andric FileInfoSize < sizeof(*FileInfo)) 6200b57cec5SDimitry Andric return Version; 6210b57cec5SDimitry Andric 6220b57cec5SDimitry Andric const unsigned Major = (FileInfo->dwFileVersionMS >> 16) & 0xFFFF; 6230b57cec5SDimitry Andric const unsigned Minor = (FileInfo->dwFileVersionMS ) & 0xFFFF; 6240b57cec5SDimitry Andric const unsigned Micro = (FileInfo->dwFileVersionLS >> 16) & 0xFFFF; 6250b57cec5SDimitry Andric 6260b57cec5SDimitry Andric Version = VersionTuple(Major, Minor, Micro); 6270b57cec5SDimitry Andric #endif 6280b57cec5SDimitry Andric return Version; 6290b57cec5SDimitry Andric } 6300b57cec5SDimitry Andric 6310b57cec5SDimitry Andric void MSVCToolChain::AddSystemIncludeWithSubfolder( 6320b57cec5SDimitry Andric const ArgList &DriverArgs, ArgStringList &CC1Args, 6330b57cec5SDimitry Andric const std::string &folder, const Twine &subfolder1, const Twine &subfolder2, 6340b57cec5SDimitry Andric const Twine &subfolder3) const { 6350b57cec5SDimitry Andric llvm::SmallString<128> path(folder); 6360b57cec5SDimitry Andric llvm::sys::path::append(path, subfolder1, subfolder2, subfolder3); 6370b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, path); 6380b57cec5SDimitry Andric } 6390b57cec5SDimitry Andric 6400b57cec5SDimitry Andric void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 6410b57cec5SDimitry Andric ArgStringList &CC1Args) const { 6420b57cec5SDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdinc)) 6430b57cec5SDimitry Andric return; 6440b57cec5SDimitry Andric 6450b57cec5SDimitry Andric if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 6460b57cec5SDimitry Andric AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, getDriver().ResourceDir, 6470b57cec5SDimitry Andric "include"); 6480b57cec5SDimitry Andric } 6490b57cec5SDimitry Andric 6500b57cec5SDimitry Andric // Add %INCLUDE%-like directories from the -imsvc flag. 6510b57cec5SDimitry Andric for (const auto &Path : DriverArgs.getAllArgValues(options::OPT__SLASH_imsvc)) 6520b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, Path); 6530b57cec5SDimitry Andric 654fe6060f1SDimitry Andric auto AddSystemIncludesFromEnv = [&](StringRef Var) -> bool { 655fe6060f1SDimitry Andric if (auto Val = llvm::sys::Process::GetEnv(Var)) { 656fe6060f1SDimitry Andric SmallVector<StringRef, 8> Dirs; 657fe6060f1SDimitry Andric StringRef(*Val).split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false); 658fe6060f1SDimitry Andric if (!Dirs.empty()) { 659fe6060f1SDimitry Andric addSystemIncludes(DriverArgs, CC1Args, Dirs); 660fe6060f1SDimitry Andric return true; 661fe6060f1SDimitry Andric } 662fe6060f1SDimitry Andric } 663fe6060f1SDimitry Andric return false; 664fe6060f1SDimitry Andric }; 665fe6060f1SDimitry Andric 666fe6060f1SDimitry Andric // Add %INCLUDE%-like dirs via /external:env: flags. 667fe6060f1SDimitry Andric for (const auto &Var : 668fe6060f1SDimitry Andric DriverArgs.getAllArgValues(options::OPT__SLASH_external_env)) { 669fe6060f1SDimitry Andric AddSystemIncludesFromEnv(Var); 670fe6060f1SDimitry Andric } 671fe6060f1SDimitry Andric 672349cc55cSDimitry Andric // Add DIA SDK include if requested. 673349cc55cSDimitry Andric if (const Arg *A = DriverArgs.getLastArg(options::OPT__SLASH_diasdkdir, 674349cc55cSDimitry Andric options::OPT__SLASH_winsysroot)) { 675349cc55cSDimitry Andric // cl.exe doesn't find the DIA SDK automatically, so this too requires 676349cc55cSDimitry Andric // explicit flags and doesn't automatically look in "DIA SDK" relative 677349cc55cSDimitry Andric // to the path we found for VCToolChainPath. 678349cc55cSDimitry Andric llvm::SmallString<128> DIASDKPath(A->getValue()); 679349cc55cSDimitry Andric if (A->getOption().getID() == options::OPT__SLASH_winsysroot) 680349cc55cSDimitry Andric llvm::sys::path::append(DIASDKPath, "DIA SDK"); 681349cc55cSDimitry Andric AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, std::string(DIASDKPath), 682349cc55cSDimitry Andric "include"); 683349cc55cSDimitry Andric } 684349cc55cSDimitry Andric 6850b57cec5SDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 6860b57cec5SDimitry Andric return; 6870b57cec5SDimitry Andric 688fe6060f1SDimitry Andric // Honor %INCLUDE% and %EXTERNAL_INCLUDE%. It should have essential search 689fe6060f1SDimitry Andric // paths set by vcvarsall.bat. Skip if the user expressly set a vctoolsdir. 690fe6060f1SDimitry Andric if (!DriverArgs.getLastArg(options::OPT__SLASH_vctoolsdir, 691fe6060f1SDimitry Andric options::OPT__SLASH_winsysroot)) { 692fe6060f1SDimitry Andric bool Found = AddSystemIncludesFromEnv("INCLUDE"); 693fe6060f1SDimitry Andric Found |= AddSystemIncludesFromEnv("EXTERNAL_INCLUDE"); 694fe6060f1SDimitry Andric if (Found) 6950b57cec5SDimitry Andric return; 6960b57cec5SDimitry Andric } 6970b57cec5SDimitry Andric 6980b57cec5SDimitry Andric // When built with access to the proper Windows APIs, try to actually find 6990b57cec5SDimitry Andric // the correct include paths first. 7000b57cec5SDimitry Andric if (!VCToolChainPath.empty()) { 7010b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, 70281ad6265SDimitry Andric getSubDirectoryPath(llvm::SubDirectoryType::Include)); 70381ad6265SDimitry Andric addSystemInclude( 70481ad6265SDimitry Andric DriverArgs, CC1Args, 70581ad6265SDimitry Andric getSubDirectoryPath(llvm::SubDirectoryType::Include, "atlmfc")); 7060b57cec5SDimitry Andric 7070b57cec5SDimitry Andric if (useUniversalCRT()) { 7080b57cec5SDimitry Andric std::string UniversalCRTSdkPath; 7090b57cec5SDimitry Andric std::string UCRTVersion; 71081ad6265SDimitry Andric if (llvm::getUniversalCRTSdkDir(getVFS(), WinSdkDir, WinSdkVersion, 71181ad6265SDimitry Andric WinSysRoot, UniversalCRTSdkPath, 712fe6060f1SDimitry Andric UCRTVersion)) { 71306c3fb27SDimitry Andric if (!(WinSdkDir.has_value() || WinSysRoot.has_value()) && 71406c3fb27SDimitry Andric WinSdkVersion.has_value()) 71506c3fb27SDimitry Andric UCRTVersion = *WinSdkVersion; 7160b57cec5SDimitry Andric AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath, 7170b57cec5SDimitry Andric "Include", UCRTVersion, "ucrt"); 7180b57cec5SDimitry Andric } 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric 7210b57cec5SDimitry Andric std::string WindowsSDKDir; 722fe6060f1SDimitry Andric int major = 0; 7230b57cec5SDimitry Andric std::string windowsSDKIncludeVersion; 7240b57cec5SDimitry Andric std::string windowsSDKLibVersion; 72581ad6265SDimitry Andric if (llvm::getWindowsSDKDir(getVFS(), WinSdkDir, WinSdkVersion, WinSysRoot, 72681ad6265SDimitry Andric WindowsSDKDir, major, windowsSDKIncludeVersion, 72781ad6265SDimitry Andric windowsSDKLibVersion)) { 72806c3fb27SDimitry Andric if (major >= 10) 72906c3fb27SDimitry Andric if (!(WinSdkDir.has_value() || WinSysRoot.has_value()) && 73006c3fb27SDimitry Andric WinSdkVersion.has_value()) 73106c3fb27SDimitry Andric windowsSDKIncludeVersion = windowsSDKLibVersion = *WinSdkVersion; 7320b57cec5SDimitry Andric if (major >= 8) { 7330b57cec5SDimitry Andric // Note: windowsSDKIncludeVersion is empty for SDKs prior to v10. 7340b57cec5SDimitry Andric // Anyway, llvm::sys::path::append is able to manage it. 7350b57cec5SDimitry Andric AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 736fe6060f1SDimitry Andric "Include", windowsSDKIncludeVersion, 7370b57cec5SDimitry Andric "shared"); 7380b57cec5SDimitry Andric AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 739fe6060f1SDimitry Andric "Include", windowsSDKIncludeVersion, 7400b57cec5SDimitry Andric "um"); 7410b57cec5SDimitry Andric AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 742fe6060f1SDimitry Andric "Include", windowsSDKIncludeVersion, 7430b57cec5SDimitry Andric "winrt"); 74404eeddc0SDimitry Andric if (major >= 10) { 74504eeddc0SDimitry Andric llvm::VersionTuple Tuple; 74604eeddc0SDimitry Andric if (!Tuple.tryParse(windowsSDKIncludeVersion) && 74781ad6265SDimitry Andric Tuple.getSubminor().value_or(0) >= 17134) { 74804eeddc0SDimitry Andric AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 74904eeddc0SDimitry Andric "Include", windowsSDKIncludeVersion, 75004eeddc0SDimitry Andric "cppwinrt"); 75104eeddc0SDimitry Andric } 75204eeddc0SDimitry Andric } 7530b57cec5SDimitry Andric } else { 7540b57cec5SDimitry Andric AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 755fe6060f1SDimitry Andric "Include"); 7560b57cec5SDimitry Andric } 7570b57cec5SDimitry Andric } 7580b57cec5SDimitry Andric 7590b57cec5SDimitry Andric return; 7600b57cec5SDimitry Andric } 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric #if defined(_WIN32) 7630b57cec5SDimitry Andric // As a fallback, select default install paths. 7640b57cec5SDimitry Andric // FIXME: Don't guess drives and paths like this on Windows. 7650b57cec5SDimitry Andric const StringRef Paths[] = { 7660b57cec5SDimitry Andric "C:/Program Files/Microsoft Visual Studio 10.0/VC/include", 7670b57cec5SDimitry Andric "C:/Program Files/Microsoft Visual Studio 9.0/VC/include", 7680b57cec5SDimitry Andric "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include", 7690b57cec5SDimitry Andric "C:/Program Files/Microsoft Visual Studio 8/VC/include", 7700b57cec5SDimitry Andric "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include" 7710b57cec5SDimitry Andric }; 7720b57cec5SDimitry Andric addSystemIncludes(DriverArgs, CC1Args, Paths); 7730b57cec5SDimitry Andric #endif 7740b57cec5SDimitry Andric } 7750b57cec5SDimitry Andric 7760b57cec5SDimitry Andric void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, 7770b57cec5SDimitry Andric ArgStringList &CC1Args) const { 7780b57cec5SDimitry Andric // FIXME: There should probably be logic here to find libc++ on Windows. 7790b57cec5SDimitry Andric } 7800b57cec5SDimitry Andric 7810b57cec5SDimitry Andric VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D, 7820b57cec5SDimitry Andric const ArgList &Args) const { 7830b57cec5SDimitry Andric bool IsWindowsMSVC = getTriple().isWindowsMSVCEnvironment(); 7840b57cec5SDimitry Andric VersionTuple MSVT = ToolChain::computeMSVCVersion(D, Args); 7850b57cec5SDimitry Andric if (MSVT.empty()) 7860eae32dcSDimitry Andric MSVT = getTriple().getEnvironmentVersion(); 7870b57cec5SDimitry Andric if (MSVT.empty() && IsWindowsMSVC) 78881ad6265SDimitry Andric MSVT = 78981ad6265SDimitry Andric getMSVCVersionFromExe(getSubDirectoryPath(llvm::SubDirectoryType::Bin)); 7900b57cec5SDimitry Andric if (MSVT.empty() && 7910b57cec5SDimitry Andric Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, 7920b57cec5SDimitry Andric IsWindowsMSVC)) { 7935f757f3fSDimitry Andric // -fms-compatibility-version=19.33 is default, aka 2022, 17.3 79406c3fb27SDimitry Andric // NOTE: when changing this value, also update 79506c3fb27SDimitry Andric // clang/docs/CommandGuide/clang.rst and clang/docs/UsersManual.rst 79606c3fb27SDimitry Andric // accordingly. 7975f757f3fSDimitry Andric MSVT = VersionTuple(19, 33); 7980b57cec5SDimitry Andric } 7990b57cec5SDimitry Andric return MSVT; 8000b57cec5SDimitry Andric } 8010b57cec5SDimitry Andric 8020b57cec5SDimitry Andric std::string 8030b57cec5SDimitry Andric MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args, 8040b57cec5SDimitry Andric types::ID InputType) const { 8050b57cec5SDimitry Andric // The MSVC version doesn't care about the architecture, even though it 8060b57cec5SDimitry Andric // may look at the triple internally. 8070b57cec5SDimitry Andric VersionTuple MSVT = computeMSVCVersion(/*D=*/nullptr, Args); 80881ad6265SDimitry Andric MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().value_or(0), 80981ad6265SDimitry Andric MSVT.getSubminor().value_or(0)); 8100b57cec5SDimitry Andric 8110b57cec5SDimitry Andric // For the rest of the triple, however, a computed architecture name may 8120b57cec5SDimitry Andric // be needed. 8130b57cec5SDimitry Andric llvm::Triple Triple(ToolChain::ComputeEffectiveClangTriple(Args, InputType)); 8140b57cec5SDimitry Andric if (Triple.getEnvironment() == llvm::Triple::MSVC) { 8150b57cec5SDimitry Andric StringRef ObjFmt = Triple.getEnvironmentName().split('-').second; 8160b57cec5SDimitry Andric if (ObjFmt.empty()) 8170b57cec5SDimitry Andric Triple.setEnvironmentName((Twine("msvc") + MSVT.getAsString()).str()); 8180b57cec5SDimitry Andric else 8190b57cec5SDimitry Andric Triple.setEnvironmentName( 8200b57cec5SDimitry Andric (Twine("msvc") + MSVT.getAsString() + Twine('-') + ObjFmt).str()); 8210b57cec5SDimitry Andric } 8220b57cec5SDimitry Andric return Triple.getTriple(); 8230b57cec5SDimitry Andric } 8240b57cec5SDimitry Andric 8250b57cec5SDimitry Andric SanitizerMask MSVCToolChain::getSupportedSanitizers() const { 8260b57cec5SDimitry Andric SanitizerMask Res = ToolChain::getSupportedSanitizers(); 8270b57cec5SDimitry Andric Res |= SanitizerKind::Address; 8280b57cec5SDimitry Andric Res |= SanitizerKind::PointerCompare; 8290b57cec5SDimitry Andric Res |= SanitizerKind::PointerSubtract; 8300b57cec5SDimitry Andric Res |= SanitizerKind::Fuzzer; 8310b57cec5SDimitry Andric Res |= SanitizerKind::FuzzerNoLink; 8320b57cec5SDimitry Andric Res &= ~SanitizerKind::CFIMFCall; 8330b57cec5SDimitry Andric return Res; 8340b57cec5SDimitry Andric } 8350b57cec5SDimitry Andric 8360b57cec5SDimitry Andric static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL, 8370b57cec5SDimitry Andric bool SupportsForcingFramePointer, 8380b57cec5SDimitry Andric const char *ExpandChar, const OptTable &Opts) { 8390b57cec5SDimitry Andric assert(A->getOption().matches(options::OPT__SLASH_O)); 8400b57cec5SDimitry Andric 8410b57cec5SDimitry Andric StringRef OptStr = A->getValue(); 8420b57cec5SDimitry Andric for (size_t I = 0, E = OptStr.size(); I != E; ++I) { 8430b57cec5SDimitry Andric const char &OptChar = *(OptStr.data() + I); 8440b57cec5SDimitry Andric switch (OptChar) { 8450b57cec5SDimitry Andric default: 8460b57cec5SDimitry Andric break; 8470b57cec5SDimitry Andric case '1': 8480b57cec5SDimitry Andric case '2': 8490b57cec5SDimitry Andric case 'x': 8500b57cec5SDimitry Andric case 'd': 8510b57cec5SDimitry Andric // Ignore /O[12xd] flags that aren't the last one on the command line. 8520b57cec5SDimitry Andric // Only the last one gets expanded. 8530b57cec5SDimitry Andric if (&OptChar != ExpandChar) { 8540b57cec5SDimitry Andric A->claim(); 8550b57cec5SDimitry Andric break; 8560b57cec5SDimitry Andric } 8570b57cec5SDimitry Andric if (OptChar == 'd') { 8580b57cec5SDimitry Andric DAL.AddFlagArg(A, Opts.getOption(options::OPT_O0)); 8590b57cec5SDimitry Andric } else { 8600b57cec5SDimitry Andric if (OptChar == '1') { 8610b57cec5SDimitry Andric DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s"); 8620b57cec5SDimitry Andric } else if (OptChar == '2' || OptChar == 'x') { 8630b57cec5SDimitry Andric DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin)); 864*0fca6ea1SDimitry Andric DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "3"); 8650b57cec5SDimitry Andric } 8660b57cec5SDimitry Andric if (SupportsForcingFramePointer && 8670b57cec5SDimitry Andric !DAL.hasArgNoClaim(options::OPT_fno_omit_frame_pointer)) 8680b57cec5SDimitry Andric DAL.AddFlagArg(A, Opts.getOption(options::OPT_fomit_frame_pointer)); 8690b57cec5SDimitry Andric if (OptChar == '1' || OptChar == '2') 8700b57cec5SDimitry Andric DAL.AddFlagArg(A, Opts.getOption(options::OPT_ffunction_sections)); 8710b57cec5SDimitry Andric } 8720b57cec5SDimitry Andric break; 8730b57cec5SDimitry Andric case 'b': 8740b57cec5SDimitry Andric if (I + 1 != E && isdigit(OptStr[I + 1])) { 8750b57cec5SDimitry Andric switch (OptStr[I + 1]) { 8760b57cec5SDimitry Andric case '0': 8770b57cec5SDimitry Andric DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_inline)); 8780b57cec5SDimitry Andric break; 8790b57cec5SDimitry Andric case '1': 8800b57cec5SDimitry Andric DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_hint_functions)); 8810b57cec5SDimitry Andric break; 8820b57cec5SDimitry Andric case '2': 883*0fca6ea1SDimitry Andric case '3': 8840b57cec5SDimitry Andric DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_functions)); 8850b57cec5SDimitry Andric break; 8860b57cec5SDimitry Andric } 8870b57cec5SDimitry Andric ++I; 8880b57cec5SDimitry Andric } 8890b57cec5SDimitry Andric break; 8900b57cec5SDimitry Andric case 'g': 8910b57cec5SDimitry Andric A->claim(); 8920b57cec5SDimitry Andric break; 8930b57cec5SDimitry Andric case 'i': 8940b57cec5SDimitry Andric if (I + 1 != E && OptStr[I + 1] == '-') { 8950b57cec5SDimitry Andric ++I; 8960b57cec5SDimitry Andric DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin)); 8970b57cec5SDimitry Andric } else { 8980b57cec5SDimitry Andric DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin)); 8990b57cec5SDimitry Andric } 9000b57cec5SDimitry Andric break; 9010b57cec5SDimitry Andric case 's': 9020b57cec5SDimitry Andric DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s"); 9030b57cec5SDimitry Andric break; 9040b57cec5SDimitry Andric case 't': 905*0fca6ea1SDimitry Andric DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "3"); 9060b57cec5SDimitry Andric break; 9070b57cec5SDimitry Andric case 'y': { 9080b57cec5SDimitry Andric bool OmitFramePointer = true; 9090b57cec5SDimitry Andric if (I + 1 != E && OptStr[I + 1] == '-') { 9100b57cec5SDimitry Andric OmitFramePointer = false; 9110b57cec5SDimitry Andric ++I; 9120b57cec5SDimitry Andric } 9130b57cec5SDimitry Andric if (SupportsForcingFramePointer) { 9140b57cec5SDimitry Andric if (OmitFramePointer) 9150b57cec5SDimitry Andric DAL.AddFlagArg(A, 9160b57cec5SDimitry Andric Opts.getOption(options::OPT_fomit_frame_pointer)); 9170b57cec5SDimitry Andric else 9180b57cec5SDimitry Andric DAL.AddFlagArg( 9190b57cec5SDimitry Andric A, Opts.getOption(options::OPT_fno_omit_frame_pointer)); 9200b57cec5SDimitry Andric } else { 9210b57cec5SDimitry Andric // Don't warn about /Oy- in x86-64 builds (where 9220b57cec5SDimitry Andric // SupportsForcingFramePointer is false). The flag having no effect 9230b57cec5SDimitry Andric // there is a compiler-internal optimization, and people shouldn't have 9240b57cec5SDimitry Andric // to special-case their build files for x86-64 clang-cl. 9250b57cec5SDimitry Andric A->claim(); 9260b57cec5SDimitry Andric } 9270b57cec5SDimitry Andric break; 9280b57cec5SDimitry Andric } 9290b57cec5SDimitry Andric } 9300b57cec5SDimitry Andric } 9310b57cec5SDimitry Andric } 9320b57cec5SDimitry Andric 9330b57cec5SDimitry Andric static void TranslateDArg(Arg *A, llvm::opt::DerivedArgList &DAL, 9340b57cec5SDimitry Andric const OptTable &Opts) { 9350b57cec5SDimitry Andric assert(A->getOption().matches(options::OPT_D)); 9360b57cec5SDimitry Andric 9370b57cec5SDimitry Andric StringRef Val = A->getValue(); 9380b57cec5SDimitry Andric size_t Hash = Val.find('#'); 9390b57cec5SDimitry Andric if (Hash == StringRef::npos || Hash > Val.find('=')) { 9400b57cec5SDimitry Andric DAL.append(A); 9410b57cec5SDimitry Andric return; 9420b57cec5SDimitry Andric } 9430b57cec5SDimitry Andric 9445ffd83dbSDimitry Andric std::string NewVal = std::string(Val); 9450b57cec5SDimitry Andric NewVal[Hash] = '='; 9460b57cec5SDimitry Andric DAL.AddJoinedArg(A, Opts.getOption(options::OPT_D), NewVal); 9470b57cec5SDimitry Andric } 9480b57cec5SDimitry Andric 949fe6060f1SDimitry Andric static void TranslatePermissive(Arg *A, llvm::opt::DerivedArgList &DAL, 950fe6060f1SDimitry Andric const OptTable &Opts) { 951fe6060f1SDimitry Andric DAL.AddFlagArg(A, Opts.getOption(options::OPT__SLASH_Zc_twoPhase_)); 952fe6060f1SDimitry Andric DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_operator_names)); 953fe6060f1SDimitry Andric } 954fe6060f1SDimitry Andric 955fe6060f1SDimitry Andric static void TranslatePermissiveMinus(Arg *A, llvm::opt::DerivedArgList &DAL, 956fe6060f1SDimitry Andric const OptTable &Opts) { 957fe6060f1SDimitry Andric DAL.AddFlagArg(A, Opts.getOption(options::OPT__SLASH_Zc_twoPhase)); 958fe6060f1SDimitry Andric DAL.AddFlagArg(A, Opts.getOption(options::OPT_foperator_names)); 959fe6060f1SDimitry Andric } 960fe6060f1SDimitry Andric 9610b57cec5SDimitry Andric llvm::opt::DerivedArgList * 9620b57cec5SDimitry Andric MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args, 9635ffd83dbSDimitry Andric StringRef BoundArch, 9645ffd83dbSDimitry Andric Action::OffloadKind OFK) const { 9650b57cec5SDimitry Andric DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); 9660b57cec5SDimitry Andric const OptTable &Opts = getDriver().getOpts(); 9670b57cec5SDimitry Andric 9680b57cec5SDimitry Andric // /Oy and /Oy- don't have an effect on X86-64 9690b57cec5SDimitry Andric bool SupportsForcingFramePointer = getArch() != llvm::Triple::x86_64; 9700b57cec5SDimitry Andric 9710b57cec5SDimitry Andric // The -O[12xd] flag actually expands to several flags. We must desugar the 9720b57cec5SDimitry Andric // flags so that options embedded can be negated. For example, the '-O2' flag 9730b57cec5SDimitry Andric // enables '-Oy'. Expanding '-O2' into its constituent flags allows us to 9740b57cec5SDimitry Andric // correctly handle '-O2 -Oy-' where the trailing '-Oy-' disables a single 9750b57cec5SDimitry Andric // aspect of '-O2'. 9760b57cec5SDimitry Andric // 9770b57cec5SDimitry Andric // Note that this expansion logic only applies to the *last* of '[12xd]'. 9780b57cec5SDimitry Andric 9790b57cec5SDimitry Andric // First step is to search for the character we'd like to expand. 9800b57cec5SDimitry Andric const char *ExpandChar = nullptr; 9810b57cec5SDimitry Andric for (Arg *A : Args.filtered(options::OPT__SLASH_O)) { 9820b57cec5SDimitry Andric StringRef OptStr = A->getValue(); 9830b57cec5SDimitry Andric for (size_t I = 0, E = OptStr.size(); I != E; ++I) { 9840b57cec5SDimitry Andric char OptChar = OptStr[I]; 9850b57cec5SDimitry Andric char PrevChar = I > 0 ? OptStr[I - 1] : '0'; 9860b57cec5SDimitry Andric if (PrevChar == 'b') { 9870b57cec5SDimitry Andric // OptChar does not expand; it's an argument to the previous char. 9880b57cec5SDimitry Andric continue; 9890b57cec5SDimitry Andric } 9900b57cec5SDimitry Andric if (OptChar == '1' || OptChar == '2' || OptChar == 'x' || OptChar == 'd') 9910b57cec5SDimitry Andric ExpandChar = OptStr.data() + I; 9920b57cec5SDimitry Andric } 9930b57cec5SDimitry Andric } 9940b57cec5SDimitry Andric 9950b57cec5SDimitry Andric for (Arg *A : Args) { 9960b57cec5SDimitry Andric if (A->getOption().matches(options::OPT__SLASH_O)) { 9970b57cec5SDimitry Andric // The -O flag actually takes an amalgam of other options. For example, 9980b57cec5SDimitry Andric // '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'. 9990b57cec5SDimitry Andric TranslateOptArg(A, *DAL, SupportsForcingFramePointer, ExpandChar, Opts); 10000b57cec5SDimitry Andric } else if (A->getOption().matches(options::OPT_D)) { 10010b57cec5SDimitry Andric // Translate -Dfoo#bar into -Dfoo=bar. 10020b57cec5SDimitry Andric TranslateDArg(A, *DAL, Opts); 1003fe6060f1SDimitry Andric } else if (A->getOption().matches(options::OPT__SLASH_permissive)) { 1004fe6060f1SDimitry Andric // Expand /permissive 1005fe6060f1SDimitry Andric TranslatePermissive(A, *DAL, Opts); 1006fe6060f1SDimitry Andric } else if (A->getOption().matches(options::OPT__SLASH_permissive_)) { 1007fe6060f1SDimitry Andric // Expand /permissive- 1008fe6060f1SDimitry Andric TranslatePermissiveMinus(A, *DAL, Opts); 10095ffd83dbSDimitry Andric } else if (OFK != Action::OFK_HIP) { 10105ffd83dbSDimitry Andric // HIP Toolchain translates input args by itself. 10110b57cec5SDimitry Andric DAL->append(A); 10120b57cec5SDimitry Andric } 10130b57cec5SDimitry Andric } 10140b57cec5SDimitry Andric 10150b57cec5SDimitry Andric return DAL; 10160b57cec5SDimitry Andric } 1017fe6060f1SDimitry Andric 1018fe6060f1SDimitry Andric void MSVCToolChain::addClangTargetOptions( 1019fe6060f1SDimitry Andric const ArgList &DriverArgs, ArgStringList &CC1Args, 1020fe6060f1SDimitry Andric Action::OffloadKind DeviceOffloadKind) const { 1021fe6060f1SDimitry Andric // MSVC STL kindly allows removing all usages of typeid by defining 1022fe6060f1SDimitry Andric // _HAS_STATIC_RTTI to 0. Do so, when compiling with -fno-rtti 102381ad6265SDimitry Andric if (DriverArgs.hasFlag(options::OPT_fno_rtti, options::OPT_frtti, 1024fe6060f1SDimitry Andric /*Default=*/false)) 1025fe6060f1SDimitry Andric CC1Args.push_back("-D_HAS_STATIC_RTTI=0"); 1026*0fca6ea1SDimitry Andric 1027*0fca6ea1SDimitry Andric if (Arg *A = DriverArgs.getLastArgNoClaim(options::OPT_marm64x)) 1028*0fca6ea1SDimitry Andric A->ignoreTargetSpecific(); 1029fe6060f1SDimitry Andric } 1030