#include "MSVC.h"
#include "CommonArgs.h"
#include "Darwin.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/VirtualFileSystem.h"
#include <cstdio>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#define NOGDI
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#endif
using namespace clang::driver;
using namespace clang::driver::toolchains;
using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
static bool canExecute(llvm::vfs::FileSystem &VFS, StringRef Path) {
auto Status = VFS.status(Path);
if (!Status)
return false;
return (Status->getPermissions() & llvm::sys::fs::perms::all_exe) != 0;
}
static std::string FindVisualStudioExecutable(const ToolChain &TC,
const char *Exe) {
const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC);
SmallString<128> FilePath(
MSVC.getSubDirectoryPath(llvm::SubDirectoryType::Bin));
llvm::sys::path::append(FilePath, Exe);
return std::string(canExecute(TC.getVFS(), FilePath) ? FilePath.str() : Exe);
}
void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
ArgStringList CmdArgs;
auto &TC = static_cast<const toolchains::MSVCToolChain &>(getToolChain());
assert((Output.isFilename() || Output.isNothing()) && "invalid output");
if (Output.isFilename())
CmdArgs.push_back(
Args.MakeArgString(std::string("-out:") + Output.getFilename()));
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) &&
!C.getDriver().IsCLMode() && !C.getDriver().IsFlangMode()) {
CmdArgs.push_back("-defaultlib:libcmt");
CmdArgs.push_back("-defaultlib:oldnames");
}
if (const Arg *A = Args.getLastArg(options::OPT__SLASH_diasdkdir,
options::OPT__SLASH_winsysroot)) {
llvm::SmallString<128> DIAPath(A->getValue());
if (A->getOption().getID() == options::OPT__SLASH_winsysroot)
llvm::sys::path::append(DIAPath, "DIA SDK");
llvm::sys::path::append(DIAPath, "lib",
llvm::archToLegacyVCArch(TC.getArch()));
CmdArgs.push_back(Args.MakeArgString(Twine("-libpath:") + DIAPath));
}
if (!llvm::sys::Process::GetEnv("LIB") ||
Args.getLastArg(options::OPT__SLASH_vctoolsdir,
options::OPT__SLASH_winsysroot)) {
CmdArgs.push_back(Args.MakeArgString(
Twine("-libpath:") +
TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib)));
CmdArgs.push_back(Args.MakeArgString(
Twine("-libpath:") +
TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib, "atlmfc")));
}
if (!llvm::sys::Process::GetEnv("LIB") ||
Args.getLastArg(options::OPT__SLASH_winsdkdir,
options::OPT__SLASH_winsysroot)) {
if (TC.useUniversalCRT()) {
std::string UniversalCRTLibPath;
if (TC.getUniversalCRTLibraryPath(Args, UniversalCRTLibPath))
CmdArgs.push_back(
Args.MakeArgString(Twine("-libpath:") + UniversalCRTLibPath));
}
std::string WindowsSdkLibPath;
if (TC.getWindowsSDKLibraryPath(Args, WindowsSdkLibPath))
CmdArgs.push_back(
Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath));
}
if (C.getDriver().IsFlangMode()) {
addFortranRuntimeLibraryPath(TC, Args, CmdArgs);
addFortranRuntimeLibs(TC, CmdArgs);
CmdArgs.push_back("/subsystem:console");
}
for (const auto &LibPath : TC.getLibraryPaths()) {
if (TC.getVFS().exists(LibPath))
CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath));
}
auto CRTPath = TC.getCompilerRTPath();
if (TC.getVFS().exists(CRTPath))
CmdArgs.push_back(Args.MakeArgString("-libpath:" + CRTPath));
if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L))
for (const auto &LibPath : Args.getAllArgValues(options::OPT_L))
CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath));
CmdArgs.push_back("-nologo");
if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7))
CmdArgs.push_back("-debug");
if (Args.hasArg(options::OPT_fms_hotpatch, options::OPT__SLASH_hotpatch))
CmdArgs.push_back("-functionpadmin");
bool DefaultIncrementalLinkerCompatible =
C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment();
if (!Args.hasFlag(options::OPT_mincremental_linker_compatible,
options::OPT_mno_incremental_linker_compatible,
DefaultIncrementalLinkerCompatible))
CmdArgs.push_back("-Brepro");
bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd,
options::OPT_shared);
if (DLL) {
CmdArgs.push_back(Args.MakeArgString("-dll"));
SmallString<128> ImplibName(Output.getFilename());
llvm::sys::path::replace_extension(ImplibName, "lib");
CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName));
}
if (TC.getSanitizerArgs(Args).needsFuzzer()) {
if (!Args.hasArg(options::OPT_shared))
CmdArgs.push_back(
Args.MakeArgString(std::string("-wholearchive:") +
TC.getCompilerRTArgString(Args, "fuzzer")));
CmdArgs.push_back(Args.MakeArgString("-debug"));
CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
}
if (TC.getSanitizerArgs(Args).needsAsanRt()) {
CmdArgs.push_back(Args.MakeArgString("-debug"));
CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
if (TC.getSanitizerArgs(Args).needsSharedRt() ||
Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
CmdArgs.push_back(Args.MakeArgString(
TC.getArch() == llvm::Triple::x86
? "-include:___asan_seh_interceptor"
: "-include:__asan_seh_interceptor"));
CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
TC.getCompilerRT(Args, "asan_dynamic_runtime_thunk")));
} else if (DLL) {
CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
} else {
for (const auto &Lib : {"asan", "asan_cxx"}) {
CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
TC.getCompilerRT(Args, Lib)));
}
}
}
Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link);
if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) {
StringRef GuardArgs = A->getValue();
if (GuardArgs.equals_insensitive("cf") ||
GuardArgs.equals_insensitive("cf,nochecks")) {
CmdArgs.push_back("-guard:cf");
} else if (GuardArgs.equals_insensitive("cf-")) {
CmdArgs.push_back("-guard:cf-");
} else if (GuardArgs.equals_insensitive("ehcont")) {
CmdArgs.push_back("-guard:ehcont");
} else if (GuardArgs.equals_insensitive("ehcont-")) {
CmdArgs.push_back("-guard:ehcont-");
}
}
if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
options::OPT_fno_openmp, false)) {
CmdArgs.push_back("-nodefaultlib:vcomp.lib");
CmdArgs.push_back("-nodefaultlib:vcompd.lib");
CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
TC.getDriver().Dir + "/../lib"));
switch (TC.getDriver().getOpenMPRuntime(Args)) {
case Driver::OMPRT_OMP:
CmdArgs.push_back("-defaultlib:libomp.lib");
break;
case Driver::OMPRT_IOMP5:
CmdArgs.push_back("-defaultlib:libiomp5md.lib");
break;
case Driver::OMPRT_GOMP:
break;
case Driver::OMPRT_Unknown:
break;
}
}
if (!Args.hasArg(options::OPT_nostdlib)) {
AddRunTimeLibs(TC, TC.getDriver(), CmdArgs, Args);
}
for (const auto &Input : Inputs) {
if (Input.isFilename()) {
CmdArgs.push_back(Input.getFilename());
continue;
}
const Arg &A = Input.getInputArg();
if (A.getOption().matches(options::OPT_l)) {
StringRef Lib = A.getValue();
const char *LinkLibArg;
if (Lib.endswith(".lib"))
LinkLibArg = Args.MakeArgString(Lib);
else
LinkLibArg = Args.MakeArgString(Lib + ".lib");
CmdArgs.push_back(LinkLibArg);
continue;
}
A.renderAsInput(Args, CmdArgs);
}
addHIPRuntimeLibArgs(TC, Args, CmdArgs);
TC.addProfileRTLibs(Args, CmdArgs);
std::vector<const char *> Environment;
llvm::SmallString<128> linkPath;
StringRef Linker
= Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER);
if (Linker.empty())
Linker = "link";
if (Linker.equals_insensitive("lld"))
Linker = "lld-link";
if (Linker.equals_insensitive("link")) {
linkPath = FindVisualStudioExecutable(TC, "link.exe");
if (!TC.FoundMSVCInstall() && !canExecute(TC.getVFS(), linkPath)) {
llvm::SmallString<128> ClPath;
ClPath = TC.GetProgramPath("cl.exe");
if (canExecute(TC.getVFS(), ClPath)) {
linkPath = llvm::sys::path::parent_path(ClPath);
llvm::sys::path::append(linkPath, "link.exe");
if (!canExecute(TC.getVFS(), linkPath))
C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
} else {
C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
}
}
#ifdef _WIN32
if (TC.getIsVS2017OrNewer() &&
llvm::Triple(llvm::sys::getProcessTriple()).getArch() != TC.getArch()) {
auto HostArch = llvm::Triple(llvm::sys::getProcessTriple()).getArch();
auto EnvBlockWide =
std::unique_ptr<wchar_t[], decltype(&FreeEnvironmentStringsW)>(
GetEnvironmentStringsW(), FreeEnvironmentStringsW);
if (!EnvBlockWide)
goto SkipSettingEnvironment;
size_t EnvCount = 0;
size_t EnvBlockLen = 0;
while (EnvBlockWide[EnvBlockLen] != L'\0') {
++EnvCount;
EnvBlockLen += std::wcslen(&EnvBlockWide[EnvBlockLen]) +
1 ;
}
++EnvBlockLen;
std::string EnvBlock;
if (!llvm::convertUTF16ToUTF8String(
llvm::ArrayRef<char>(reinterpret_cast<char *>(EnvBlockWide.get()),
EnvBlockLen * sizeof(EnvBlockWide[0])),
EnvBlock))
goto SkipSettingEnvironment;
Environment.reserve(EnvCount);
for (const char *Cursor = EnvBlock.data(); *Cursor != '\0';) {
llvm::StringRef EnvVar(Cursor);
if (EnvVar.startswith_insensitive("path=")) {
constexpr size_t PrefixLen = 5; Environment.push_back(Args.MakeArgString(
EnvVar.substr(0, PrefixLen) +
TC.getSubDirectoryPath(llvm::SubDirectoryType::Bin) +
llvm::Twine(llvm::sys::EnvPathSeparator) +
TC.getSubDirectoryPath(llvm::SubDirectoryType::Bin, HostArch) +
(EnvVar.size() > PrefixLen
? llvm::Twine(llvm::sys::EnvPathSeparator) +
EnvVar.substr(PrefixLen)
: "")));
} else {
Environment.push_back(Args.MakeArgString(EnvVar));
}
Cursor += EnvVar.size() + 1 ;
}
}
SkipSettingEnvironment:;
#endif
} else {
linkPath = TC.GetProgramPath(Linker.str().c_str());
}
auto LinkCmd = std::make_unique<Command>(
JA, *this, ResponseFileSupport::AtFileUTF16(),
Args.MakeArgString(linkPath), CmdArgs, Inputs, Output);
if (!Environment.empty())
LinkCmd->setEnvironment(Environment);
C.addCommand(std::move(LinkCmd));
}
MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args),
RocmInstallation(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
Optional<llvm::StringRef> VCToolsDir, VCToolsVersion;
if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir))
VCToolsDir = A->getValue();
if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsversion))
VCToolsVersion = A->getValue();
if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkdir))
WinSdkDir = A->getValue();
if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkversion))
WinSdkVersion = A->getValue();
if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsysroot))
WinSysRoot = A->getValue();
llvm::findVCToolChainViaCommandLine(getVFS(), VCToolsDir, VCToolsVersion,
WinSysRoot, VCToolChainPath, VSLayout) ||
llvm::findVCToolChainViaEnvironment(getVFS(), VCToolChainPath,
VSLayout) ||
llvm::findVCToolChainViaSetupConfig(getVFS(), VCToolChainPath,
VSLayout) ||
llvm::findVCToolChainViaRegistry(VCToolChainPath, VSLayout);
}
Tool *MSVCToolChain::buildLinker() const {
return new tools::visualstudio::Linker(*this);
}
Tool *MSVCToolChain::buildAssembler() const {
if (getTriple().isOSBinFormatMachO())
return new tools::darwin::Assembler(*this);
getDriver().Diag(clang::diag::err_no_external_assembler);
return nullptr;
}
bool MSVCToolChain::IsIntegratedAssemblerDefault() const {
return true;
}
bool MSVCToolChain::IsUnwindTablesDefault(const ArgList &Args) const {
if (getTriple().isOSBinFormatMachO())
return false;
return getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::arm ||
getArch() == llvm::Triple::thumb || getArch() == llvm::Triple::aarch64;
}
bool MSVCToolChain::isPICDefault() const {
return getArch() == llvm::Triple::x86_64 ||
getArch() == llvm::Triple::aarch64;
}
bool MSVCToolChain::isPIEDefault(const llvm::opt::ArgList &Args) const {
return false;
}
bool MSVCToolChain::isPICDefaultForced() const {
return getArch() == llvm::Triple::x86_64 ||
getArch() == llvm::Triple::aarch64;
}
void MSVCToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
}
void MSVCToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
}
void MSVCToolChain::AddHIPRuntimeLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
CmdArgs.append({Args.MakeArgString(StringRef("-libpath:") +
RocmInstallation.getLibPath()),
"amdhip64.lib"});
}
void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const {
CudaInstallation.print(OS);
RocmInstallation.print(OS);
}
std::string
MSVCToolChain::getSubDirectoryPath(llvm::SubDirectoryType Type,
llvm::StringRef SubdirParent) const {
return llvm::getSubDirectoryPath(Type, VSLayout, VCToolChainPath, getArch(),
SubdirParent);
}
std::string
MSVCToolChain::getSubDirectoryPath(llvm::SubDirectoryType Type,
llvm::Triple::ArchType TargetArch) const {
return llvm::getSubDirectoryPath(Type, VSLayout, VCToolChainPath, TargetArch,
"");
}
bool MSVCToolChain::getWindowsSDKLibraryPath(const ArgList &Args,
std::string &path) const {
std::string sdkPath;
int sdkMajor = 0;
std::string windowsSDKIncludeVersion;
std::string windowsSDKLibVersion;
path.clear();
if (!llvm::getWindowsSDKDir(getVFS(), WinSdkDir, WinSdkVersion, WinSysRoot,
sdkPath, sdkMajor, windowsSDKIncludeVersion,
windowsSDKLibVersion))
return false;
llvm::SmallString<128> libPath(sdkPath);
llvm::sys::path::append(libPath, "Lib");
if (sdkMajor >= 8)
llvm::sys::path::append(libPath, windowsSDKLibVersion, "um");
return llvm::appendArchToWindowsSDKLibPath(sdkMajor, libPath, getArch(),
path);
}
bool MSVCToolChain::useUniversalCRT() const {
return llvm::useUniversalCRT(VSLayout, VCToolChainPath, getArch(), getVFS());
}
bool MSVCToolChain::getUniversalCRTLibraryPath(const ArgList &Args,
std::string &Path) const {
std::string UniversalCRTSdkPath;
std::string UCRTVersion;
Path.clear();
if (!llvm::getUniversalCRTSdkDir(getVFS(), WinSdkDir, WinSdkVersion,
WinSysRoot, UniversalCRTSdkPath,
UCRTVersion))
return false;
StringRef ArchName = llvm::archToWindowsSDKArch(getArch());
if (ArchName.empty())
return false;
llvm::SmallString<128> LibPath(UniversalCRTSdkPath);
llvm::sys::path::append(LibPath, "Lib", UCRTVersion, "ucrt", ArchName);
Path = std::string(LibPath.str());
return true;
}
static VersionTuple getMSVCVersionFromExe(const std::string &BinDir) {
VersionTuple Version;
#ifdef _WIN32
SmallString<128> ClExe(BinDir);
llvm::sys::path::append(ClExe, "cl.exe");
std::wstring ClExeWide;
if (!llvm::ConvertUTF8toWide(ClExe.c_str(), ClExeWide))
return Version;
const DWORD VersionSize = ::GetFileVersionInfoSizeW(ClExeWide.c_str(),
nullptr);
if (VersionSize == 0)
return Version;
SmallVector<uint8_t, 4 * 1024> VersionBlock(VersionSize);
if (!::GetFileVersionInfoW(ClExeWide.c_str(), 0, VersionSize,
VersionBlock.data()))
return Version;
VS_FIXEDFILEINFO *FileInfo = nullptr;
UINT FileInfoSize = 0;
if (!::VerQueryValueW(VersionBlock.data(), L"\\",
reinterpret_cast<LPVOID *>(&FileInfo), &FileInfoSize) ||
FileInfoSize < sizeof(*FileInfo))
return Version;
const unsigned Major = (FileInfo->dwFileVersionMS >> 16) & 0xFFFF;
const unsigned Minor = (FileInfo->dwFileVersionMS ) & 0xFFFF;
const unsigned Micro = (FileInfo->dwFileVersionLS >> 16) & 0xFFFF;
Version = VersionTuple(Major, Minor, Micro);
#endif
return Version;
}
void MSVCToolChain::AddSystemIncludeWithSubfolder(
const ArgList &DriverArgs, ArgStringList &CC1Args,
const std::string &folder, const Twine &subfolder1, const Twine &subfolder2,
const Twine &subfolder3) const {
llvm::SmallString<128> path(folder);
llvm::sys::path::append(path, subfolder1, subfolder2, subfolder3);
addSystemInclude(DriverArgs, CC1Args, path);
}
void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdinc))
return;
if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, getDriver().ResourceDir,
"include");
}
for (const auto &Path : DriverArgs.getAllArgValues(options::OPT__SLASH_imsvc))
addSystemInclude(DriverArgs, CC1Args, Path);
auto AddSystemIncludesFromEnv = [&](StringRef Var) -> bool {
if (auto Val = llvm::sys::Process::GetEnv(Var)) {
SmallVector<StringRef, 8> Dirs;
StringRef(*Val).split(Dirs, ";", -1, false);
if (!Dirs.empty()) {
addSystemIncludes(DriverArgs, CC1Args, Dirs);
return true;
}
}
return false;
};
for (const auto &Var :
DriverArgs.getAllArgValues(options::OPT__SLASH_external_env)) {
AddSystemIncludesFromEnv(Var);
}
if (const Arg *A = DriverArgs.getLastArg(options::OPT__SLASH_diasdkdir,
options::OPT__SLASH_winsysroot)) {
llvm::SmallString<128> DIASDKPath(A->getValue());
if (A->getOption().getID() == options::OPT__SLASH_winsysroot)
llvm::sys::path::append(DIASDKPath, "DIA SDK");
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, std::string(DIASDKPath),
"include");
}
if (DriverArgs.hasArg(options::OPT_nostdlibinc))
return;
if (!DriverArgs.getLastArg(options::OPT__SLASH_vctoolsdir,
options::OPT__SLASH_winsysroot)) {
bool Found = AddSystemIncludesFromEnv("INCLUDE");
Found |= AddSystemIncludesFromEnv("EXTERNAL_INCLUDE");
if (Found)
return;
}
if (!VCToolChainPath.empty()) {
addSystemInclude(DriverArgs, CC1Args,
getSubDirectoryPath(llvm::SubDirectoryType::Include));
addSystemInclude(
DriverArgs, CC1Args,
getSubDirectoryPath(llvm::SubDirectoryType::Include, "atlmfc"));
if (useUniversalCRT()) {
std::string UniversalCRTSdkPath;
std::string UCRTVersion;
if (llvm::getUniversalCRTSdkDir(getVFS(), WinSdkDir, WinSdkVersion,
WinSysRoot, UniversalCRTSdkPath,
UCRTVersion)) {
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath,
"Include", UCRTVersion, "ucrt");
}
}
std::string WindowsSDKDir;
int major = 0;
std::string windowsSDKIncludeVersion;
std::string windowsSDKLibVersion;
if (llvm::getWindowsSDKDir(getVFS(), WinSdkDir, WinSdkVersion, WinSysRoot,
WindowsSDKDir, major, windowsSDKIncludeVersion,
windowsSDKLibVersion)) {
if (major >= 8) {
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
"Include", windowsSDKIncludeVersion,
"shared");
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
"Include", windowsSDKIncludeVersion,
"um");
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
"Include", windowsSDKIncludeVersion,
"winrt");
if (major >= 10) {
llvm::VersionTuple Tuple;
if (!Tuple.tryParse(windowsSDKIncludeVersion) &&
Tuple.getSubminor().value_or(0) >= 17134) {
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
"Include", windowsSDKIncludeVersion,
"cppwinrt");
}
}
} else {
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
"Include");
}
}
return;
}
#if defined(_WIN32)
const StringRef Paths[] = {
"C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
"C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
"C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
"C:/Program Files/Microsoft Visual Studio 8/VC/include",
"C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
};
addSystemIncludes(DriverArgs, CC1Args, Paths);
#endif
}
void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
}
VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D,
const ArgList &Args) const {
bool IsWindowsMSVC = getTriple().isWindowsMSVCEnvironment();
VersionTuple MSVT = ToolChain::computeMSVCVersion(D, Args);
if (MSVT.empty())
MSVT = getTriple().getEnvironmentVersion();
if (MSVT.empty() && IsWindowsMSVC)
MSVT =
getMSVCVersionFromExe(getSubDirectoryPath(llvm::SubDirectoryType::Bin));
if (MSVT.empty() &&
Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
IsWindowsMSVC)) {
MSVT = VersionTuple(19, 20);
}
return MSVT;
}
std::string
MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
types::ID InputType) const {
VersionTuple MSVT = computeMSVCVersion(nullptr, Args);
MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().value_or(0),
MSVT.getSubminor().value_or(0));
llvm::Triple Triple(ToolChain::ComputeEffectiveClangTriple(Args, InputType));
if (Triple.getEnvironment() == llvm::Triple::MSVC) {
StringRef ObjFmt = Triple.getEnvironmentName().split('-').second;
if (ObjFmt.empty())
Triple.setEnvironmentName((Twine("msvc") + MSVT.getAsString()).str());
else
Triple.setEnvironmentName(
(Twine("msvc") + MSVT.getAsString() + Twine('-') + ObjFmt).str());
}
return Triple.getTriple();
}
SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
SanitizerMask Res = ToolChain::getSupportedSanitizers();
Res |= SanitizerKind::Address;
Res |= SanitizerKind::PointerCompare;
Res |= SanitizerKind::PointerSubtract;
Res |= SanitizerKind::Fuzzer;
Res |= SanitizerKind::FuzzerNoLink;
Res &= ~SanitizerKind::CFIMFCall;
return Res;
}
static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL,
bool SupportsForcingFramePointer,
const char *ExpandChar, const OptTable &Opts) {
assert(A->getOption().matches(options::OPT__SLASH_O));
StringRef OptStr = A->getValue();
for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
const char &OptChar = *(OptStr.data() + I);
switch (OptChar) {
default:
break;
case '1':
case '2':
case 'x':
case 'd':
if (&OptChar != ExpandChar) {
A->claim();
break;
}
if (OptChar == 'd') {
DAL.AddFlagArg(A, Opts.getOption(options::OPT_O0));
} else {
if (OptChar == '1') {
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
} else if (OptChar == '2' || OptChar == 'x') {
DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
}
if (SupportsForcingFramePointer &&
!DAL.hasArgNoClaim(options::OPT_fno_omit_frame_pointer))
DAL.AddFlagArg(A, Opts.getOption(options::OPT_fomit_frame_pointer));
if (OptChar == '1' || OptChar == '2')
DAL.AddFlagArg(A, Opts.getOption(options::OPT_ffunction_sections));
}
break;
case 'b':
if (I + 1 != E && isdigit(OptStr[I + 1])) {
switch (OptStr[I + 1]) {
case '0':
DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_inline));
break;
case '1':
DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_hint_functions));
break;
case '2':
DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_functions));
break;
}
++I;
}
break;
case 'g':
A->claim();
break;
case 'i':
if (I + 1 != E && OptStr[I + 1] == '-') {
++I;
DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin));
} else {
DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
}
break;
case 's':
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
break;
case 't':
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
break;
case 'y': {
bool OmitFramePointer = true;
if (I + 1 != E && OptStr[I + 1] == '-') {
OmitFramePointer = false;
++I;
}
if (SupportsForcingFramePointer) {
if (OmitFramePointer)
DAL.AddFlagArg(A,
Opts.getOption(options::OPT_fomit_frame_pointer));
else
DAL.AddFlagArg(
A, Opts.getOption(options::OPT_fno_omit_frame_pointer));
} else {
A->claim();
}
break;
}
}
}
}
static void TranslateDArg(Arg *A, llvm::opt::DerivedArgList &DAL,
const OptTable &Opts) {
assert(A->getOption().matches(options::OPT_D));
StringRef Val = A->getValue();
size_t Hash = Val.find('#');
if (Hash == StringRef::npos || Hash > Val.find('=')) {
DAL.append(A);
return;
}
std::string NewVal = std::string(Val);
NewVal[Hash] = '=';
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_D), NewVal);
}
static void TranslatePermissive(Arg *A, llvm::opt::DerivedArgList &DAL,
const OptTable &Opts) {
DAL.AddFlagArg(A, Opts.getOption(options::OPT__SLASH_Zc_twoPhase_));
DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_operator_names));
}
static void TranslatePermissiveMinus(Arg *A, llvm::opt::DerivedArgList &DAL,
const OptTable &Opts) {
DAL.AddFlagArg(A, Opts.getOption(options::OPT__SLASH_Zc_twoPhase));
DAL.AddFlagArg(A, Opts.getOption(options::OPT_foperator_names));
}
llvm::opt::DerivedArgList *
MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
StringRef BoundArch,
Action::OffloadKind OFK) const {
DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
const OptTable &Opts = getDriver().getOpts();
bool SupportsForcingFramePointer = getArch() != llvm::Triple::x86_64;
const char *ExpandChar = nullptr;
for (Arg *A : Args.filtered(options::OPT__SLASH_O)) {
StringRef OptStr = A->getValue();
for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
char OptChar = OptStr[I];
char PrevChar = I > 0 ? OptStr[I - 1] : '0';
if (PrevChar == 'b') {
continue;
}
if (OptChar == '1' || OptChar == '2' || OptChar == 'x' || OptChar == 'd')
ExpandChar = OptStr.data() + I;
}
}
for (Arg *A : Args) {
if (A->getOption().matches(options::OPT__SLASH_O)) {
TranslateOptArg(A, *DAL, SupportsForcingFramePointer, ExpandChar, Opts);
} else if (A->getOption().matches(options::OPT_D)) {
TranslateDArg(A, *DAL, Opts);
} else if (A->getOption().matches(options::OPT__SLASH_permissive)) {
TranslatePermissive(A, *DAL, Opts);
} else if (A->getOption().matches(options::OPT__SLASH_permissive_)) {
TranslatePermissiveMinus(A, *DAL, Opts);
} else if (OFK != Action::OFK_HIP) {
DAL->append(A);
}
}
return DAL;
}
void MSVCToolChain::addClangTargetOptions(
const ArgList &DriverArgs, ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadKind) const {
if (DriverArgs.hasFlag(options::OPT_fno_rtti, options::OPT_frtti,
false))
CC1Args.push_back("-D_HAS_STATIC_RTTI=0");
}