diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -641,6 +641,8 @@ case llvm::Triple::Solaris: return std::make_unique>(Triple, Opts); + case llvm::Triple::UEFI: + return std::make_unique(Triple, Opts); case llvm::Triple::Win32: { switch (Triple.getEnvironment()) { case llvm::Triple::Cygnus: diff --git a/clang/lib/Basic/Targets/OSTargets.h b/clang/lib/Basic/Targets/OSTargets.h --- a/clang/lib/Basic/Targets/OSTargets.h +++ b/clang/lib/Basic/Targets/OSTargets.h @@ -843,6 +843,23 @@ } }; +// UEFI target +template +class LLVM_LIBRARY_VISIBILITY UEFITargetInfo : public OSTargetInfo { +protected: + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { + Builder.defineMacro("__UEFI__"); + } + +public: + UEFITargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : OSTargetInfo(Triple, Opts) { + this->WCharType = TargetInfo::UnsignedShort; + this->WIntType = TargetInfo::UnsignedShort; + } +}; + void addWindowsDefines(const llvm::Triple &Triple, const LangOptions &Opts, MacroBuilder &Builder); diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -808,6 +808,61 @@ } }; +// x86-64 UEFI target +class LLVM_LIBRARY_VISIBILITY UEFIX86_64TargetInfo + : public UEFITargetInfo { +public: + UEFIX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : UEFITargetInfo(Triple, Opts) { + LongWidth = LongAlign = 32; + DoubleAlign = LongLongAlign = 64; + IntMaxType = SignedLongLong; + Int64Type = SignedLongLong; + SizeType = UnsignedLongLong; + PtrDiffType = SignedLongLong; + IntPtrType = SignedLongLong; + LongDoubleWidth = LongDoubleAlign = 64; + LongDoubleFormat = &llvm::APFloat::IEEEdouble(); + } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + Builder.defineMacro("_M_X64", "100"); + Builder.defineMacro("_M_AMD64", "100"); + } + + BuiltinVaListKind getBuiltinVaListKind() const override { + return TargetInfo::CharPtrBuiltinVaList; + } + + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { + switch (CC) { + case CC_X86StdCall: + case CC_X86ThisCall: + case CC_X86FastCall: + return CCCR_Ignore; + case CC_C: + case CC_X86VectorCall: + case CC_IntelOclBicc: + case CC_PreserveMost: + case CC_PreserveAll: + case CC_X86_64SysV: + case CC_Swift: + case CC_SwiftAsync: + case CC_X86RegCall: + case CC_OpenCLKernel: + return CCCR_OK; + default: + return CCCR_Warning; + } + } + + TargetInfo::CallingConvKind + getCallingConvKind(bool ClangABICompat4) const override { + return CCK_MicrosoftWin64; + } +}; + // x86-64 Windows target class LLVM_LIBRARY_VISIBILITY WindowsX86_64TargetInfo : public WindowsTargetInfo { diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -6147,6 +6147,10 @@ case llvm::Triple::Mesa3D: TC = std::make_unique(*this, Target, Args); break; + case llvm::Triple::UEFI: + TC = std::make_unique(*this, Target, Args); + ////TODO(prabhukr): Replace with a new UEFI toolchain + break; case llvm::Triple::Win32: switch (Target.getEnvironment()) { default: diff --git a/clang/lib/Driver/ToolChains/UEFI.h b/clang/lib/Driver/ToolChains/UEFI.h new file mode 100644 --- /dev/null +++ b/clang/lib/Driver/ToolChains/UEFI.h @@ -0,0 +1,58 @@ +//===--- UEFI.h - UEFI ToolChain Implementations ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_UEFI_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_UEFI_H +#include "clang/Driver/Tool.h" +#include "clang/Driver/ToolChain.h" + +namespace clang { +namespace driver { +namespace tools { +namespace uefi { +class LLVM_LIBRARY_VISIBILITY Linker : public Tool { +public: + Linker(const ToolChain &TC) : Tool("uefi::Linker", "lld-link", TC) {} + + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return true; } + + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; +}; +} // end namespace uefi +} // end namespace tools + +namespace toolchains { + +class LLVM_LIBRARY_VISIBILITY UEFI : public ToolChain { +public: + UEFI(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args); + +protected: + Tool *buildLinker() const override; + +public: + bool HasNativeLLVMSupport() const override { return true; } + bool IsIntegratedAssemblerDefault() const override { return true; } + bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const { + return true; + } + bool isPICDefault() const override { return true; } + bool isPIEDefault(const llvm::opt::ArgList &Args) const override { + return false; + } + bool isPICDefaultForced() const override { return true; } +}; +} // namespace toolchains +} // namespace driver +} // namespace clang +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_UEFI_H diff --git a/clang/lib/Driver/ToolChains/UEFI.cpp b/clang/lib/Driver/ToolChains/UEFI.cpp new file mode 100644 --- /dev/null +++ b/clang/lib/Driver/ToolChains/UEFI.cpp @@ -0,0 +1,437 @@ +//===--- UEFI.h - UEFI ToolChain Implementations ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "UEFI.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/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/FileSystem.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/VirtualFileSystem.h" + +using namespace clang::driver; +using namespace clang::driver::toolchains; +using namespace clang; +using namespace llvm::opt; + +UEFI::UEFI(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) + : ToolChain(D, Triple, Args) { + getProgramPaths().push_back(getDriver().getInstalledDir()); + if (getDriver().getInstalledDir() != getDriver().Dir) + getProgramPaths().push_back(getDriver().Dir); +} +Tool *UEFI::buildLinker() const { return new tools::uefi::Linker(*this); } + + + + + + + + + + + + + + + + + + + + + + + + + + + +void tools::uefi::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(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 the VC environment hasn't been configured (perhaps because the user + // did not run vcvarsall), try to build a consistent link environment. If + // the environment variable is set however, assume the user knows what + // they're doing. If the user passes /vctoolsdir or /winsdkdir, trust that + // over env vars. + if (const Arg *A = Args.getLastArg(options::OPT__SLASH_diasdkdir, + options::OPT__SLASH_winsysroot)) { + // cl.exe doesn't find the DIA SDK automatically, so this too requires + // explicit flags and doesn't automatically look in "DIA SDK" relative + // to the path we found for VCToolChainPath. + llvm::SmallString<128> DIAPath(A->getValue()); + if (A->getOption().getID() == options::OPT__SLASH_winsysroot) + llvm::sys::path::append(DIAPath, "DIA SDK"); + + // The DIA SDK always uses the legacy vc arch, even in new MSVC versions. + 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); +// +// // Inform the MSVC linker that we're generating a console application, i.e. +// // one with `main` as the "user-defined" entry point. The `main` function is +// // defined in flang's runtime libraries. +// CmdArgs.push_back("/subsystem:console"); +// } + + // Add the compiler-rt library directories to libpath if they exist to help + // the linker find the various sanitizer, builtin, and profiling runtimes. + 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 we specify /hotpatch, let the linker add padding in front of each + // function, like MSVC does. + if (Args.hasArg(options::OPT_fms_hotpatch, options::OPT__SLASH_hotpatch)) + CmdArgs.push_back("-functionpadmin"); + + // Pass on /Brepro if it was passed to the compiler. + // Note that /Brepro maps to -mno-incremental-linker-compatible. + 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")); + // Prevent the linker from padding sections we use for instrumentation + // arrays. + 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)); + // Make sure the dynamic runtime thunk is not optimized out at link time + // to ensure proper SEH handling. + CmdArgs.push_back(Args.MakeArgString( + TC.getArch() == llvm::Triple::x86 + ? "-include:___asan_seh_interceptor" + : "-include:__asan_seh_interceptor")); + // Make sure the linker consider all object files from the dynamic runtime + // thunk. + 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)); + // Make sure the linker consider all object files from the static lib. + // This is necessary because instrumented dlls need access to all the + // interface exported by the static lib in the main executable. + CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") + + TC.getCompilerRT(Args, Lib))); + } + } + } + + Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link); + + // Control Flow Guard checks + if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) { + StringRef GuardArgs = A->getValue(); + if (GuardArgs.equals_insensitive("cf") || + GuardArgs.equals_insensitive("cf,nochecks")) { + // MSVC doesn't yet support the "nochecks" modifier. + 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: + // Already diagnosed. + break; + } + } + + // Add compiler-rt lib in case if it was explicitly + // specified as an argument for --rtlib option. + if (!Args.hasArg(options::OPT_nostdlib)) { + AddRunTimeLibs(TC, TC.getDriver(), CmdArgs, Args); + } + + // Add filenames, libraries, and other linker inputs. + for (const auto &Input : Inputs) { + if (Input.isFilename()) { + CmdArgs.push_back(Input.getFilename()); + continue; + } + + const Arg &A = Input.getInputArg(); + + // Render -l options differently for the MSVC linker. + 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; + } + + // Otherwise, this is some other kind of linker input option like -Wl, -z, + // or -L. Render it, even if MSVC doesn't understand it. + A.renderAsInput(Args, CmdArgs); + } + + addHIPRuntimeLibArgs(TC, Args, CmdArgs); + + TC.addProfileRTLibs(Args, CmdArgs); + + std::vector Environment; + + // We need to special case some linker paths. In the case of lld, we need to + // translate 'lld' into 'lld-link', and in the case of the regular msvc + // linker, we need to use a special search algorithm. + 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")) { + // If we're using the MSVC linker, it's not sufficient to just use link + // from the program PATH, because other environments like GnuWin32 install + // their own link.exe which may come first. + 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 + // When cross-compiling with VS2017 or newer, link.exe expects to have + // its containing bin directory at the top of PATH, followed by the + // native target bin directory. + // e.g. when compiling for x86 on an x64 host, PATH should start with: + // /bin/Hostx64/x86;/bin/Hostx64/x64 + // This doesn't attempt to handle llvm::ToolsetLayout::DevDivInternal. + if (TC.getIsVS2017OrNewer() && + llvm::Triple(llvm::sys::getProcessTriple()).getArch() != TC.getArch()) { + auto HostArch = llvm::Triple(llvm::sys::getProcessTriple()).getArch(); + + auto EnvBlockWide = + std::unique_ptr( + 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 /*string null-terminator*/; + } + ++EnvBlockLen; // add the block null-terminator + + std::string EnvBlock; + if (!llvm::convertUTF16ToUTF8String( + llvm::ArrayRef(reinterpret_cast(EnvBlockWide.get()), + EnvBlockLen * sizeof(EnvBlockWide[0])), + EnvBlock)) + goto SkipSettingEnvironment; + + Environment.reserve(EnvCount); + + // Now loop over each string in the block and copy them into the + // environment vector, adjusting the PATH variable as needed when we + // find it. + for (const char *Cursor = EnvBlock.data(); *Cursor != '\0';) { + llvm::StringRef EnvVar(Cursor); + if (EnvVar.startswith_insensitive("path=")) { + constexpr size_t PrefixLen = 5; // strlen("path=") + 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 /*null-terminator*/; + } + } + SkipSettingEnvironment:; +#endif + } else { + linkPath = TC.GetProgramPath(Linker.str().c_str()); + } + + auto LinkCmd = std::make_unique( + 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); + + std::optional 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(); + + // Check the command line first, that's the user explicitly telling us what to + // use. Check the environment next, in case we're being invoked from a VS + // command prompt. Failing that, just try to find the newest Visual Studio + // version we can and use its default VC toolchain. + llvm::findVCToolChainViaCommandLine(getVFS(), VCToolsDir, VCToolsVersion, + WinSysRoot, VCToolChainPath, VSLayout) || + llvm::findVCToolChainViaEnvironment(getVFS(), VCToolChainPath, + VSLayout) || + llvm::findVCToolChainViaSetupConfig(getVFS(), VCToolChainPath, + VSLayout) || + llvm::findVCToolChainViaRegistry(VCToolChainPath, VSLayout); + +} diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -199,6 +199,7 @@ NetBSD, OpenBSD, Solaris, + UEFI, Win32, ZOS, Haiku, diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -238,6 +238,7 @@ case RTEMS: return "rtems"; case Solaris: return "solaris"; case TvOS: return "tvos"; + case UEFI: return "uefi"; case WASI: return "wasi"; case WatchOS: return "watchos"; case Win32: return "windows"; @@ -588,6 +589,7 @@ .StartsWith("netbsd", Triple::NetBSD) .StartsWith("openbsd", Triple::OpenBSD) .StartsWith("solaris", Triple::Solaris) + .StartsWith("uefi", Triple::UEFI) .StartsWith("win32", Triple::Win32) .StartsWith("windows", Triple::Win32) .StartsWith("zos", Triple::ZOS)