[llvm] 437d4e0 - Revert "try to fix windows build after 73e585e44d" and

Douglas Yung via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 11 23:49:37 PST 2022


Author: Douglas Yung
Date: 2022-02-11T23:47:53-08:00
New Revision: 437d4e01fe4c057509dff30efd560049ad07bc99

URL: https://github.com/llvm/llvm-project/commit/437d4e01fe4c057509dff30efd560049ad07bc99
DIFF: https://github.com/llvm/llvm-project/commit/437d4e01fe4c057509dff30efd560049ad07bc99.diff

LOG: Revert "try to fix windows build after 73e585e44d" and
Revert "Reland "[lld/coff] Make lld-link work in a non-MSVC shell, add /winsysroot:""

This reverts commit 0574b5fc657451c9d13d3f6d8fe14ea15c23a681 and 73e585e44d68cf77e2e3274e98c9615156a7d909.

This change is causing the test Driver/cl-options.c to fail on Windows buildbots.
https://lab.llvm.org/staging/#/builders/204/builds/1343

Added: 
    clang/lib/Driver/ToolChains/MSVCSetupApi.h

Modified: 
    clang/docs/tools/clang-formatted-files.txt
    clang/lib/Driver/CMakeLists.txt
    clang/lib/Driver/ToolChains/MSVC.cpp
    clang/lib/Driver/ToolChains/MSVC.h
    lld/COFF/CMakeLists.txt
    lld/COFF/Driver.cpp
    lld/COFF/Driver.h
    lld/COFF/Options.td
    lld/COFF/SymbolTable.cpp
    lld/docs/ReleaseNotes.rst
    llvm/lib/CMakeLists.txt
    llvm/utils/gn/secondary/clang/lib/Driver/BUILD.gn
    llvm/utils/gn/secondary/lld/COFF/BUILD.gn

Removed: 
    lld/test/COFF/winsysroot.test
    llvm/include/llvm/WindowsDriver/MSVCPaths.h
    llvm/include/llvm/WindowsDriver/MSVCSetupApi.h
    llvm/lib/WindowsDriver/CMakeLists.txt
    llvm/lib/WindowsDriver/MSVCPaths.cpp
    llvm/utils/gn/secondary/llvm/lib/WindowsDriver/BUILD.gn


################################################################################
diff  --git a/clang/docs/tools/clang-formatted-files.txt b/clang/docs/tools/clang-formatted-files.txt
index 4a2c28bcf32ae..c7defa9cd88c6 100644
--- a/clang/docs/tools/clang-formatted-files.txt
+++ b/clang/docs/tools/clang-formatted-files.txt
@@ -285,6 +285,7 @@ clang/lib/Driver/ToolChains/InterfaceStubs.h
 clang/lib/Driver/ToolChains/Minix.h
 clang/lib/Driver/ToolChains/MipsLinux.cpp
 clang/lib/Driver/ToolChains/MSP430.h
+clang/lib/Driver/ToolChains/MSVCSetupApi.h
 clang/lib/Driver/ToolChains/PPCFreeBSD.cpp
 clang/lib/Driver/ToolChains/PPCFreeBSD.h
 clang/lib/Driver/ToolChains/PPCLinux.h
@@ -5328,8 +5329,6 @@ llvm/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h
 llvm/include/llvm/Transforms/Utils/UnifyLoopExits.h
 llvm/include/llvm/Transforms/Utils/ValueMapper.h
 llvm/include/llvm/Transforms/Vectorize/SLPVectorizer.h
-llvm/include/llvm/WindowsDriver/MSVCPaths.h
-llvm/include/llvm/WindowsDriver/MSVCSetupApi.h
 llvm/include/llvm/WindowsManifest/WindowsManifestMerger.h
 llvm/include/llvm/WindowsResource/ResourceScriptToken.h
 llvm/include/llvm/XRay/BlockIndexer.h
@@ -6493,7 +6492,6 @@ llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
 llvm/lib/Transforms/Vectorize/VPlanTransforms.h
 llvm/lib/Transforms/Vectorize/VPlanValue.h
 llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp
-llvm/lib/WindowsDriver/MSVCPaths.cpp
 llvm/lib/WindowsManifest/WindowsManifestMerger.cpp
 llvm/lib/XRay/BlockIndexer.cpp
 llvm/lib/XRay/BlockVerifier.cpp

diff  --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt
index 00c7a8f893ff4..78e8fd1852841 100644
--- a/clang/lib/Driver/CMakeLists.txt
+++ b/clang/lib/Driver/CMakeLists.txt
@@ -4,7 +4,6 @@ set(LLVM_LINK_COMPONENTS
   Option
   ProfileData
   Support
-  WindowsDriver
   )
 
 if(WIN32)

diff  --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp
index 03e941389aca4..9f4751167ac12 100644
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -40,12 +40,91 @@
   #include <windows.h>
 #endif
 
+#ifdef _MSC_VER
+// Don't support SetupApi on MinGW.
+#define USE_MSVC_SETUP_API
+
+// Make sure this comes before MSVCSetupApi.h
+#include <comdef.h>
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
+#endif
+#include "MSVCSetupApi.h"
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+#include "llvm/Support/COM.h"
+_COM_SMARTPTR_TYPEDEF(ISetupConfiguration, __uuidof(ISetupConfiguration));
+_COM_SMARTPTR_TYPEDEF(ISetupConfiguration2, __uuidof(ISetupConfiguration2));
+_COM_SMARTPTR_TYPEDEF(ISetupHelper, __uuidof(ISetupHelper));
+_COM_SMARTPTR_TYPEDEF(IEnumSetupInstances, __uuidof(IEnumSetupInstances));
+_COM_SMARTPTR_TYPEDEF(ISetupInstance, __uuidof(ISetupInstance));
+_COM_SMARTPTR_TYPEDEF(ISetupInstance2, __uuidof(ISetupInstance2));
+#endif
+
 using namespace clang::driver;
 using namespace clang::driver::toolchains;
 using namespace clang::driver::tools;
 using namespace clang;
 using namespace llvm::opt;
 
+// Windows SDKs and VC Toolchains group their contents into subdirectories based
+// on the target architecture. This function converts an llvm::Triple::ArchType
+// to the corresponding subdirectory name.
+static const char *llvmArchToWindowsSDKArch(llvm::Triple::ArchType Arch) {
+  using ArchType = llvm::Triple::ArchType;
+  switch (Arch) {
+  case ArchType::x86:
+    return "x86";
+  case ArchType::x86_64:
+    return "x64";
+  case ArchType::arm:
+    return "arm";
+  case ArchType::aarch64:
+    return "arm64";
+  default:
+    return "";
+  }
+}
+
+// Similar to the above function, but for Visual Studios before VS2017.
+static const char *llvmArchToLegacyVCArch(llvm::Triple::ArchType Arch) {
+  using ArchType = llvm::Triple::ArchType;
+  switch (Arch) {
+  case ArchType::x86:
+    // x86 is default in legacy VC toolchains.
+    // e.g. x86 libs are directly in /lib as opposed to /lib/x86.
+    return "";
+  case ArchType::x86_64:
+    return "amd64";
+  case ArchType::arm:
+    return "arm";
+  case ArchType::aarch64:
+    return "arm64";
+  default:
+    return "";
+  }
+}
+
+// Similar to the above function, but for DevDiv internal builds.
+static const char *llvmArchToDevDivInternalArch(llvm::Triple::ArchType Arch) {
+  using ArchType = llvm::Triple::ArchType;
+  switch (Arch) {
+  case ArchType::x86:
+    return "i386";
+  case ArchType::x86_64:
+    return "amd64";
+  case ArchType::arm:
+    return "arm";
+  case ArchType::aarch64:
+    return "arm64";
+  default:
+    return "";
+  }
+}
+
 static bool canExecute(llvm::vfs::FileSystem &VFS, StringRef Path) {
   auto Status = VFS.status(Path);
   if (!Status)
@@ -53,6 +132,294 @@ static bool canExecute(llvm::vfs::FileSystem &VFS, StringRef Path) {
   return (Status->getPermissions() & llvm::sys::fs::perms::all_exe) != 0;
 }
 
+// Defined below.
+// Forward declare this so there aren't too many things above the constructor.
+static bool getSystemRegistryString(const char *keyPath, const char *valueName,
+                                    std::string &value, std::string *phValue);
+
+static std::string getHighestNumericTupleInDirectory(llvm::vfs::FileSystem &VFS,
+                                                     StringRef Directory) {
+  std::string Highest;
+  llvm::VersionTuple HighestTuple;
+
+  std::error_code EC;
+  for (llvm::vfs::directory_iterator DirIt = VFS.dir_begin(Directory, EC),
+                                     DirEnd;
+       !EC && DirIt != DirEnd; DirIt.increment(EC)) {
+    auto Status = VFS.status(DirIt->path());
+    if (!Status || !Status->isDirectory())
+      continue;
+    StringRef CandidateName = llvm::sys::path::filename(DirIt->path());
+    llvm::VersionTuple Tuple;
+    if (Tuple.tryParse(CandidateName)) // tryParse() returns true on error.
+      continue;
+    if (Tuple > HighestTuple) {
+      HighestTuple = Tuple;
+      Highest = CandidateName.str();
+    }
+  }
+
+  return Highest;
+}
+
+// Check command line arguments to try and find a toolchain.
+static bool
+findVCToolChainViaCommandLine(llvm::vfs::FileSystem &VFS, const ArgList &Args,
+                              std::string &Path,
+                              MSVCToolChain::ToolsetLayout &VSLayout) {
+  // Don't validate the input; trust the value supplied by the user.
+  // The primary motivation is to prevent unnecessary file and registry access.
+  if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir,
+                               options::OPT__SLASH_winsysroot)) {
+    if (A->getOption().getID() == options::OPT__SLASH_winsysroot) {
+      llvm::SmallString<128> ToolsPath(A->getValue());
+      llvm::sys::path::append(ToolsPath, "VC", "Tools", "MSVC");
+      std::string VCToolsVersion;
+      if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsversion))
+        VCToolsVersion = A->getValue();
+      else
+        VCToolsVersion = getHighestNumericTupleInDirectory(VFS, ToolsPath);
+      llvm::sys::path::append(ToolsPath, VCToolsVersion);
+      Path = std::string(ToolsPath.str());
+    } else {
+      Path = A->getValue();
+    }
+    VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
+    return true;
+  }
+  return false;
+}
+
+// Check various environment variables to try and find a toolchain.
+static bool
+findVCToolChainViaEnvironment(llvm::vfs::FileSystem &VFS, std::string &Path,
+                              MSVCToolChain::ToolsetLayout &VSLayout) {
+  // These variables are typically set by vcvarsall.bat
+  // when launching a developer command prompt.
+  if (llvm::Optional<std::string> VCToolsInstallDir =
+          llvm::sys::Process::GetEnv("VCToolsInstallDir")) {
+    // This is only set by newer Visual Studios, and it leads straight to
+    // the toolchain directory.
+    Path = std::move(*VCToolsInstallDir);
+    VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
+    return true;
+  }
+  if (llvm::Optional<std::string> VCInstallDir =
+          llvm::sys::Process::GetEnv("VCINSTALLDIR")) {
+    // If the previous variable isn't set but this one is, then we've found
+    // an older Visual Studio. This variable is set by newer Visual Studios too,
+    // so this check has to appear second.
+    // In older Visual Studios, the VC directory is the toolchain.
+    Path = std::move(*VCInstallDir);
+    VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
+    return true;
+  }
+
+  // We couldn't find any VC environment variables. Let's walk through PATH and
+  // see if it leads us to a VC toolchain bin directory. If it does, pick the
+  // first one that we find.
+  if (llvm::Optional<std::string> PathEnv =
+          llvm::sys::Process::GetEnv("PATH")) {
+    llvm::SmallVector<llvm::StringRef, 8> PathEntries;
+    llvm::StringRef(*PathEnv).split(PathEntries, llvm::sys::EnvPathSeparator);
+    for (llvm::StringRef PathEntry : PathEntries) {
+      if (PathEntry.empty())
+        continue;
+
+      llvm::SmallString<256> ExeTestPath;
+
+      // If cl.exe doesn't exist, then this definitely isn't a VC toolchain.
+      ExeTestPath = PathEntry;
+      llvm::sys::path::append(ExeTestPath, "cl.exe");
+      if (!VFS.exists(ExeTestPath))
+        continue;
+
+      // cl.exe existing isn't a conclusive test for a VC toolchain; clang also
+      // has a cl.exe. So let's check for link.exe too.
+      ExeTestPath = PathEntry;
+      llvm::sys::path::append(ExeTestPath, "link.exe");
+      if (!VFS.exists(ExeTestPath))
+        continue;
+
+      // whatever/VC/bin --> old toolchain, VC dir is toolchain dir.
+      llvm::StringRef TestPath = PathEntry;
+      bool IsBin =
+          llvm::sys::path::filename(TestPath).equals_insensitive("bin");
+      if (!IsBin) {
+        // Strip any architecture subdir like "amd64".
+        TestPath = llvm::sys::path::parent_path(TestPath);
+        IsBin = llvm::sys::path::filename(TestPath).equals_insensitive("bin");
+      }
+      if (IsBin) {
+        llvm::StringRef ParentPath = llvm::sys::path::parent_path(TestPath);
+        llvm::StringRef ParentFilename = llvm::sys::path::filename(ParentPath);
+        if (ParentFilename.equals_insensitive("VC")) {
+          Path = std::string(ParentPath);
+          VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
+          return true;
+        }
+        if (ParentFilename.equals_insensitive("x86ret") ||
+            ParentFilename.equals_insensitive("x86chk") ||
+            ParentFilename.equals_insensitive("amd64ret") ||
+            ParentFilename.equals_insensitive("amd64chk")) {
+          Path = std::string(ParentPath);
+          VSLayout = MSVCToolChain::ToolsetLayout::DevDivInternal;
+          return true;
+        }
+
+      } else {
+        // This could be a new (>=VS2017) toolchain. If it is, we should find
+        // path components with these prefixes when walking backwards through
+        // the path.
+        // Note: empty strings match anything.
+        llvm::StringRef ExpectedPrefixes[] = {"",     "Host",  "bin", "",
+                                              "MSVC", "Tools", "VC"};
+
+        auto It = llvm::sys::path::rbegin(PathEntry);
+        auto End = llvm::sys::path::rend(PathEntry);
+        for (llvm::StringRef Prefix : ExpectedPrefixes) {
+          if (It == End)
+            goto NotAToolChain;
+          if (!It->startswith_insensitive(Prefix))
+            goto NotAToolChain;
+          ++It;
+        }
+
+        // We've found a new toolchain!
+        // Back up 3 times (/bin/Host/arch) to get the root path.
+        llvm::StringRef ToolChainPath(PathEntry);
+        for (int i = 0; i < 3; ++i)
+          ToolChainPath = llvm::sys::path::parent_path(ToolChainPath);
+
+        Path = std::string(ToolChainPath);
+        VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
+        return true;
+      }
+
+    NotAToolChain:
+      continue;
+    }
+  }
+  return false;
+}
+
+// Query the Setup Config server for installs, then pick the newest version
+// and find its default VC toolchain.
+// This is the preferred way to discover new Visual Studios, as they're no
+// longer listed in the registry.
+static bool
+findVCToolChainViaSetupConfig(llvm::vfs::FileSystem &VFS, std::string &Path,
+                              MSVCToolChain::ToolsetLayout &VSLayout) {
+#if !defined(USE_MSVC_SETUP_API)
+  return false;
+#else
+  // FIXME: This really should be done once in the top-level program's main
+  // function, as it may have already been initialized with a 
diff erent
+  // threading model otherwise.
+  llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::SingleThreaded);
+  HRESULT HR;
+
+  // _com_ptr_t will throw a _com_error if a COM calls fail.
+  // The LLVM coding standards forbid exception handling, so we'll have to
+  // stop them from being thrown in the first place.
+  // The destructor will put the regular error handler back when we leave
+  // this scope.
+  struct SuppressCOMErrorsRAII {
+    static void __stdcall handler(HRESULT hr, IErrorInfo *perrinfo) {}
+
+    SuppressCOMErrorsRAII() { _set_com_error_handler(handler); }
+
+    ~SuppressCOMErrorsRAII() { _set_com_error_handler(_com_raise_error); }
+
+  } COMErrorSuppressor;
+
+  ISetupConfigurationPtr Query;
+  HR = Query.CreateInstance(__uuidof(SetupConfiguration));
+  if (FAILED(HR))
+    return false;
+
+  IEnumSetupInstancesPtr EnumInstances;
+  HR = ISetupConfiguration2Ptr(Query)->EnumAllInstances(&EnumInstances);
+  if (FAILED(HR))
+    return false;
+
+  ISetupInstancePtr Instance;
+  HR = EnumInstances->Next(1, &Instance, nullptr);
+  if (HR != S_OK)
+    return false;
+
+  ISetupInstancePtr NewestInstance;
+  Optional<uint64_t> NewestVersionNum;
+  do {
+    bstr_t VersionString;
+    uint64_t VersionNum;
+    HR = Instance->GetInstallationVersion(VersionString.GetAddress());
+    if (FAILED(HR))
+      continue;
+    HR = ISetupHelperPtr(Query)->ParseVersion(VersionString, &VersionNum);
+    if (FAILED(HR))
+      continue;
+    if (!NewestVersionNum || (VersionNum > NewestVersionNum)) {
+      NewestInstance = Instance;
+      NewestVersionNum = VersionNum;
+    }
+  } while ((HR = EnumInstances->Next(1, &Instance, nullptr)) == S_OK);
+
+  if (!NewestInstance)
+    return false;
+
+  bstr_t VCPathWide;
+  HR = NewestInstance->ResolvePath(L"VC", VCPathWide.GetAddress());
+  if (FAILED(HR))
+    return false;
+
+  std::string VCRootPath;
+  llvm::convertWideToUTF8(std::wstring(VCPathWide), VCRootPath);
+
+  llvm::SmallString<256> ToolsVersionFilePath(VCRootPath);
+  llvm::sys::path::append(ToolsVersionFilePath, "Auxiliary", "Build",
+                          "Microsoft.VCToolsVersion.default.txt");
+
+  auto ToolsVersionFile = llvm::MemoryBuffer::getFile(ToolsVersionFilePath);
+  if (!ToolsVersionFile)
+    return false;
+
+  llvm::SmallString<256> ToolchainPath(VCRootPath);
+  llvm::sys::path::append(ToolchainPath, "Tools", "MSVC",
+                          ToolsVersionFile->get()->getBuffer().rtrim());
+  auto Status = VFS.status(ToolchainPath);
+  if (!Status || !Status->isDirectory())
+    return false;
+
+  Path = std::string(ToolchainPath.str());
+  VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
+  return true;
+#endif
+}
+
+// Look in the registry for Visual Studio installs, and use that to get
+// a toolchain path. VS2017 and newer don't get added to the registry.
+// So if we find something here, we know that it's an older version.
+static bool findVCToolChainViaRegistry(std::string &Path,
+                                       MSVCToolChain::ToolsetLayout &VSLayout) {
+  std::string VSInstallPath;
+  if (getSystemRegistryString(R"(SOFTWARE\Microsoft\VisualStudio\$VERSION)",
+                              "InstallDir", VSInstallPath, nullptr) ||
+      getSystemRegistryString(R"(SOFTWARE\Microsoft\VCExpress\$VERSION)",
+                              "InstallDir", VSInstallPath, nullptr)) {
+    if (!VSInstallPath.empty()) {
+      llvm::SmallString<256> VCPath(llvm::StringRef(
+          VSInstallPath.c_str(), VSInstallPath.find(R"(\Common7\IDE)")));
+      llvm::sys::path::append(VCPath, "VC");
+
+      Path = std::string(VCPath.str());
+      VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
+      return true;
+    }
+  }
+  return false;
+}
+
 // Try to find Exe from a Visual Studio distribution.  This first tries to find
 // an installed copy of Visual Studio and, failing that, looks in the PATH,
 // making sure that whatever executable that's found is not a same-named exe
@@ -60,8 +427,8 @@ static bool canExecute(llvm::vfs::FileSystem &VFS, StringRef Path) {
 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));
+  SmallString<128> FilePath(MSVC.getSubDirectoryPath(
+      toolchains::MSVCToolChain::SubDirectoryType::Bin));
   llvm::sys::path::append(FilePath, Exe);
   return std::string(canExecute(TC.getVFS(), FilePath) ? FilePath.str() : Exe);
 }
@@ -102,7 +469,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
 
     // The DIA SDK always uses the legacy vc arch, even in new MSVC versions.
     llvm::sys::path::append(DIAPath, "lib",
-                            llvm::archToLegacyVCArch(TC.getArch()));
+                            llvmArchToLegacyVCArch(TC.getArch()));
     CmdArgs.push_back(Args.MakeArgString(Twine("-libpath:") + DIAPath));
   }
   if (!llvm::sys::Process::GetEnv("LIB") ||
@@ -110,10 +477,12 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                       options::OPT__SLASH_winsysroot)) {
     CmdArgs.push_back(Args.MakeArgString(
         Twine("-libpath:") +
-        TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib)));
+        TC.getSubDirectoryPath(
+            toolchains::MSVCToolChain::SubDirectoryType::Lib)));
     CmdArgs.push_back(Args.MakeArgString(
         Twine("-libpath:") +
-        TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib, "atlmfc")));
+        TC.getSubDirectoryPath(toolchains::MSVCToolChain::SubDirectoryType::Lib,
+                               "atlmfc")));
   }
   if (!llvm::sys::Process::GetEnv("LIB") ||
       Args.getLastArg(options::OPT__SLASH_winsdkdir,
@@ -326,7 +695,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     // 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.
+    // This doesn't attempt to handle ToolsetLayout::DevDivInternal.
     if (TC.getIsVS2017OrNewer() &&
         llvm::Triple(llvm::sys::getProcessTriple()).getArch() != TC.getArch()) {
       auto HostArch = llvm::Triple(llvm::sys::getProcessTriple()).getArch();
@@ -361,12 +730,13 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
       for (const char *Cursor = EnvBlock.data(); *Cursor != '\0';) {
         llvm::StringRef EnvVar(Cursor);
         if (EnvVar.startswith_insensitive("path=")) {
+          using SubDirectoryType = toolchains::MSVCToolChain::SubDirectoryType;
           constexpr size_t PrefixLen = 5; // strlen("path=")
           Environment.push_back(Args.MakeArgString(
               EnvVar.substr(0, PrefixLen) +
-              TC.getSubDirectoryPath(llvm::SubDirectoryType::Bin) +
+              TC.getSubDirectoryPath(SubDirectoryType::Bin) +
               llvm::Twine(llvm::sys::EnvPathSeparator) +
-              TC.getSubDirectoryPath(llvm::SubDirectoryType::Bin, HostArch) +
+              TC.getSubDirectoryPath(SubDirectoryType::Bin, "", HostArch) +
               (EnvVar.size() > PrefixLen
                    ? llvm::Twine(llvm::sys::EnvPathSeparator) +
                          EnvVar.substr(PrefixLen)
@@ -399,29 +769,14 @@ MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
   if (getDriver().getInstalledDir() != getDriver().Dir)
     getProgramPaths().push_back(getDriver().Dir);
 
-  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();
-
   // 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);
+  findVCToolChainViaCommandLine(getVFS(), Args, VCToolChainPath, VSLayout) ||
+      findVCToolChainViaEnvironment(getVFS(), VCToolChainPath, VSLayout) ||
+      findVCToolChainViaSetupConfig(getVFS(), VCToolChainPath, VSLayout) ||
+      findVCToolChainViaRegistry(VCToolChainPath, VSLayout);
 }
 
 Tool *MSVCToolChain::buildLinker() const {
@@ -480,48 +835,355 @@ void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const {
   RocmInstallation.print(OS);
 }
 
+// Get the path to a specific subdirectory in the current toolchain for
+// a given target architecture.
+// VS2017 changed the VC toolchain layout, so this should be used instead
+// of hardcoding paths.
 std::string
-MSVCToolChain::getSubDirectoryPath(llvm::SubDirectoryType Type,
-                                   llvm::StringRef SubdirParent) const {
-  return llvm::getSubDirectoryPath(Type, VSLayout, VCToolChainPath, getArch(),
-                                   SubdirParent);
+MSVCToolChain::getSubDirectoryPath(SubDirectoryType Type,
+                                   llvm::StringRef SubdirParent,
+                                   llvm::Triple::ArchType TargetArch) const {
+  const char *SubdirName;
+  const char *IncludeName;
+  switch (VSLayout) {
+  case ToolsetLayout::OlderVS:
+    SubdirName = llvmArchToLegacyVCArch(TargetArch);
+    IncludeName = "include";
+    break;
+  case ToolsetLayout::VS2017OrNewer:
+    SubdirName = llvmArchToWindowsSDKArch(TargetArch);
+    IncludeName = "include";
+    break;
+  case ToolsetLayout::DevDivInternal:
+    SubdirName = llvmArchToDevDivInternalArch(TargetArch);
+    IncludeName = "inc";
+    break;
+  }
+
+  llvm::SmallString<256> Path(VCToolChainPath);
+  if (!SubdirParent.empty())
+    llvm::sys::path::append(Path, SubdirParent);
+
+  switch (Type) {
+  case SubDirectoryType::Bin:
+    if (VSLayout == ToolsetLayout::VS2017OrNewer) {
+      const bool HostIsX64 =
+          llvm::Triple(llvm::sys::getProcessTriple()).isArch64Bit();
+      const char *const HostName = HostIsX64 ? "Hostx64" : "Hostx86";
+      llvm::sys::path::append(Path, "bin", HostName, SubdirName);
+    } else { // OlderVS or DevDivInternal
+      llvm::sys::path::append(Path, "bin", SubdirName);
+    }
+    break;
+  case SubDirectoryType::Include:
+    llvm::sys::path::append(Path, IncludeName);
+    break;
+  case SubDirectoryType::Lib:
+    llvm::sys::path::append(Path, "lib", SubdirName);
+    break;
+  }
+  return std::string(Path.str());
 }
 
-std::string
-MSVCToolChain::getSubDirectoryPath(llvm::SubDirectoryType Type,
-                                   llvm::Triple::ArchType TargetArch) const {
-  return llvm::getSubDirectoryPath(Type, VSLayout, VCToolChainPath, TargetArch,
-                                   "");
+#ifdef _WIN32
+static bool readFullStringValue(HKEY hkey, const char *valueName,
+                                std::string &value) {
+  std::wstring WideValueName;
+  if (!llvm::ConvertUTF8toWide(valueName, WideValueName))
+    return false;
+
+  DWORD result = 0;
+  DWORD valueSize = 0;
+  DWORD type = 0;
+  // First just query for the required size.
+  result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, &type, NULL,
+                            &valueSize);
+  if (result != ERROR_SUCCESS || type != REG_SZ || !valueSize)
+    return false;
+  std::vector<BYTE> buffer(valueSize);
+  result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, NULL, &buffer[0],
+                            &valueSize);
+  if (result == ERROR_SUCCESS) {
+    std::wstring WideValue(reinterpret_cast<const wchar_t *>(buffer.data()),
+                           valueSize / sizeof(wchar_t));
+    if (valueSize && WideValue.back() == L'\0') {
+      WideValue.pop_back();
+    }
+    // The destination buffer must be empty as an invariant of the conversion
+    // function; but this function is sometimes called in a loop that passes in
+    // the same buffer, however. Simply clear it out so we can overwrite it.
+    value.clear();
+    return llvm::convertWideToUTF8(WideValue, value);
+  }
+  return false;
+}
+#endif
+
+/// Read registry string.
+/// This also supports a means to look for high-versioned keys by use
+/// of a $VERSION placeholder in the key path.
+/// $VERSION in the key path is a placeholder for the version number,
+/// causing the highest value path to be searched for and used.
+/// I.e. "SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
+/// There can be additional characters in the component.  Only the numeric
+/// characters are compared.  This function only searches HKLM.
+static bool getSystemRegistryString(const char *keyPath, const char *valueName,
+                                    std::string &value, std::string *phValue) {
+#ifndef _WIN32
+  return false;
+#else
+  HKEY hRootKey = HKEY_LOCAL_MACHINE;
+  HKEY hKey = NULL;
+  long lResult;
+  bool returnValue = false;
+
+  const char *placeHolder = strstr(keyPath, "$VERSION");
+  std::string bestName;
+  // If we have a $VERSION placeholder, do the highest-version search.
+  if (placeHolder) {
+    const char *keyEnd = placeHolder - 1;
+    const char *nextKey = placeHolder;
+    // Find end of previous key.
+    while ((keyEnd > keyPath) && (*keyEnd != '\\'))
+      keyEnd--;
+    // Find end of key containing $VERSION.
+    while (*nextKey && (*nextKey != '\\'))
+      nextKey++;
+    size_t partialKeyLength = keyEnd - keyPath;
+    char partialKey[256];
+    if (partialKeyLength >= sizeof(partialKey))
+      partialKeyLength = sizeof(partialKey) - 1;
+    strncpy(partialKey, keyPath, partialKeyLength);
+    partialKey[partialKeyLength] = '\0';
+    HKEY hTopKey = NULL;
+    lResult = RegOpenKeyExA(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY,
+                            &hTopKey);
+    if (lResult == ERROR_SUCCESS) {
+      char keyName[256];
+      double bestValue = 0.0;
+      DWORD index, size = sizeof(keyName) - 1;
+      for (index = 0; RegEnumKeyExA(hTopKey, index, keyName, &size, NULL, NULL,
+                                    NULL, NULL) == ERROR_SUCCESS;
+           index++) {
+        const char *sp = keyName;
+        while (*sp && !isDigit(*sp))
+          sp++;
+        if (!*sp)
+          continue;
+        const char *ep = sp + 1;
+        while (*ep && (isDigit(*ep) || (*ep == '.')))
+          ep++;
+        char numBuf[32];
+        strncpy(numBuf, sp, sizeof(numBuf) - 1);
+        numBuf[sizeof(numBuf) - 1] = '\0';
+        double dvalue = strtod(numBuf, NULL);
+        if (dvalue > bestValue) {
+          // Test that InstallDir is indeed there before keeping this index.
+          // Open the chosen key path remainder.
+          bestName = keyName;
+          // Append rest of key.
+          bestName.append(nextKey);
+          lResult = RegOpenKeyExA(hTopKey, bestName.c_str(), 0,
+                                  KEY_READ | KEY_WOW64_32KEY, &hKey);
+          if (lResult == ERROR_SUCCESS) {
+            if (readFullStringValue(hKey, valueName, value)) {
+              bestValue = dvalue;
+              if (phValue)
+                *phValue = bestName;
+              returnValue = true;
+            }
+            RegCloseKey(hKey);
+          }
+        }
+        size = sizeof(keyName) - 1;
+      }
+      RegCloseKey(hTopKey);
+    }
+  } else {
+    lResult =
+        RegOpenKeyExA(hRootKey, keyPath, 0, KEY_READ | KEY_WOW64_32KEY, &hKey);
+    if (lResult == ERROR_SUCCESS) {
+      if (readFullStringValue(hKey, valueName, value))
+        returnValue = true;
+      if (phValue)
+        phValue->clear();
+      RegCloseKey(hKey);
+    }
+  }
+  return returnValue;
+#endif // _WIN32
 }
 
 // Find the most recent version of Universal CRT or Windows 10 SDK.
 // vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include
 // directory by name and uses the last one of the list.
 // So we compare entry names lexicographically to find the greatest one.
+static bool getWindows10SDKVersionFromPath(llvm::vfs::FileSystem &VFS,
+                                           const std::string &SDKPath,
+                                           std::string &SDKVersion) {
+  llvm::SmallString<128> IncludePath(SDKPath);
+  llvm::sys::path::append(IncludePath, "Include");
+  SDKVersion = getHighestNumericTupleInDirectory(VFS, IncludePath);
+  return !SDKVersion.empty();
+}
+
+static bool getWindowsSDKDirViaCommandLine(llvm::vfs::FileSystem &VFS,
+                                           const ArgList &Args,
+                                           std::string &Path, int &Major,
+                                           std::string &Version) {
+  if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkdir,
+                               options::OPT__SLASH_winsysroot)) {
+    // Don't validate the input; trust the value supplied by the user.
+    // The motivation is to prevent unnecessary file and registry access.
+    llvm::VersionTuple SDKVersion;
+    if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkversion))
+      SDKVersion.tryParse(A->getValue());
+
+    if (A->getOption().getID() == options::OPT__SLASH_winsysroot) {
+      llvm::SmallString<128> SDKPath(A->getValue());
+      llvm::sys::path::append(SDKPath, "Windows Kits");
+      if (!SDKVersion.empty())
+        llvm::sys::path::append(SDKPath, Twine(SDKVersion.getMajor()));
+      else
+        llvm::sys::path::append(
+            SDKPath, getHighestNumericTupleInDirectory(VFS, SDKPath));
+      Path = std::string(SDKPath.str());
+    } else {
+      Path = A->getValue();
+    }
+
+    if (!SDKVersion.empty()) {
+      Major = SDKVersion.getMajor();
+      Version = SDKVersion.getAsString();
+    } else if (getWindows10SDKVersionFromPath(VFS, Path, Version)) {
+      Major = 10;
+    }
+    return true;
+  }
+  return false;
+}
+
+/// Get Windows SDK installation directory.
+static bool getWindowsSDKDir(llvm::vfs::FileSystem &VFS, const ArgList &Args,
+                             std::string &Path, int &Major,
+                             std::string &WindowsSDKIncludeVersion,
+                             std::string &WindowsSDKLibVersion) {
+  // Trust /winsdkdir and /winsdkversion if present.
+  if (getWindowsSDKDirViaCommandLine(VFS, Args, Path, Major,
+                                     WindowsSDKIncludeVersion)) {
+    WindowsSDKLibVersion = WindowsSDKIncludeVersion;
+    return true;
+  }
+
+  // FIXME: Try env vars (%WindowsSdkDir%, %UCRTVersion%) before going to registry.
+
+  // Try the Windows registry.
+  std::string RegistrySDKVersion;
+  if (!getSystemRegistryString(
+          "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
+          "InstallationFolder", Path, &RegistrySDKVersion))
+    return false;
+  if (Path.empty() || RegistrySDKVersion.empty())
+    return false;
+
+  WindowsSDKIncludeVersion.clear();
+  WindowsSDKLibVersion.clear();
+  Major = 0;
+  std::sscanf(RegistrySDKVersion.c_str(), "v%d.", &Major);
+  if (Major <= 7)
+    return true;
+  if (Major == 8) {
+    // Windows SDK 8.x installs libraries in a folder whose names depend on the
+    // version of the OS you're targeting.  By default choose the newest, which
+    // usually corresponds to the version of the OS you've installed the SDK on.
+    const char *Tests[] = {"winv6.3", "win8", "win7"};
+    for (const char *Test : Tests) {
+      llvm::SmallString<128> TestPath(Path);
+      llvm::sys::path::append(TestPath, "Lib", Test);
+      if (VFS.exists(TestPath)) {
+        WindowsSDKLibVersion = Test;
+        break;
+      }
+    }
+    return !WindowsSDKLibVersion.empty();
+  }
+  if (Major == 10) {
+    if (!getWindows10SDKVersionFromPath(VFS, Path, WindowsSDKIncludeVersion))
+      return false;
+    WindowsSDKLibVersion = WindowsSDKIncludeVersion;
+    return true;
+  }
+  // Unsupported SDK version
+  return false;
+}
+
 // Gets the library path required to link against the Windows SDK.
-bool MSVCToolChain::getWindowsSDKLibraryPath(const ArgList &Args,
-                                             std::string &path) const {
+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))
+  if (!getWindowsSDKDir(getVFS(), Args, 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);
+  if (sdkMajor >= 8) {
+    llvm::sys::path::append(libPath, windowsSDKLibVersion, "um",
+                            llvmArchToWindowsSDKArch(getArch()));
+  } else {
+    switch (getArch()) {
+    // In Windows SDK 7.x, x86 libraries are directly in the Lib folder.
+    case llvm::Triple::x86:
+      break;
+    case llvm::Triple::x86_64:
+      llvm::sys::path::append(libPath, "x64");
+      break;
+    case llvm::Triple::arm:
+      // It is not necessary to link against Windows SDK 7.x when targeting ARM.
+      return false;
+    default:
+      return false;
+    }
+  }
+
+  path = std::string(libPath.str());
+  return true;
 }
 
+// Check if the Include path of a specified version of Visual Studio contains
+// specific header files. If not, they are probably shipped with Universal CRT.
 bool MSVCToolChain::useUniversalCRT() const {
-  return llvm::useUniversalCRT(VSLayout, VCToolChainPath, getArch(), getVFS());
+  llvm::SmallString<128> TestPath(
+      getSubDirectoryPath(SubDirectoryType::Include));
+  llvm::sys::path::append(TestPath, "stdlib.h");
+  return !getVFS().exists(TestPath);
+}
+
+static bool getUniversalCRTSdkDir(llvm::vfs::FileSystem &VFS,
+                                  const ArgList &Args, std::string &Path,
+                                  std::string &UCRTVersion) {
+  // If /winsdkdir is passed, use it as location for the UCRT too.
+  // FIXME: Should there be a dedicated /ucrtdir to override /winsdkdir?
+  int Major;
+  if (getWindowsSDKDirViaCommandLine(VFS, Args, Path, Major, UCRTVersion))
+    return true;
+
+  // FIXME: Try env vars (%UniversalCRTSdkDir%, %UCRTVersion%) before going to
+  // registry.
+
+  // vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry
+  // for the specific key "KitsRoot10". So do we.
+  if (!getSystemRegistryString(
+          "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10",
+          Path, nullptr))
+    return false;
+
+  return getWindows10SDKVersionFromPath(VFS, Path, UCRTVersion);
 }
 
 bool MSVCToolChain::getUniversalCRTLibraryPath(const ArgList &Args,
@@ -530,12 +1192,10 @@ bool MSVCToolChain::getUniversalCRTLibraryPath(const ArgList &Args,
   std::string UCRTVersion;
 
   Path.clear();
-  if (!llvm::getUniversalCRTSdkDir(getVFS(), WinSdkDir, WinSdkVersion,
-                                   WinSysRoot, UniversalCRTSdkPath,
-                                   UCRTVersion))
+  if (!getUniversalCRTSdkDir(getVFS(), Args, UniversalCRTSdkPath, UCRTVersion))
     return false;
 
-  StringRef ArchName = llvm::archToWindowsSDKArch(getArch());
+  StringRef ArchName = llvmArchToWindowsSDKArch(getArch());
   if (ArchName.empty())
     return false;
 
@@ -653,17 +1313,15 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
   // the correct include paths first.
   if (!VCToolChainPath.empty()) {
     addSystemInclude(DriverArgs, CC1Args,
-                     getSubDirectoryPath(llvm::SubDirectoryType::Include));
-    addSystemInclude(
-        DriverArgs, CC1Args,
-        getSubDirectoryPath(llvm::SubDirectoryType::Include, "atlmfc"));
+                     getSubDirectoryPath(SubDirectoryType::Include));
+    addSystemInclude(DriverArgs, CC1Args,
+                     getSubDirectoryPath(SubDirectoryType::Include, "atlmfc"));
 
     if (useUniversalCRT()) {
       std::string UniversalCRTSdkPath;
       std::string UCRTVersion;
-      if (llvm::getUniversalCRTSdkDir(getVFS(), WinSdkDir, WinSdkVersion,
-                                      WinSysRoot, UniversalCRTSdkPath,
-                                      UCRTVersion)) {
+      if (getUniversalCRTSdkDir(getVFS(), DriverArgs, UniversalCRTSdkPath,
+                                UCRTVersion)) {
         AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath,
                                       "Include", UCRTVersion, "ucrt");
       }
@@ -673,9 +1331,8 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
     int major = 0;
     std::string windowsSDKIncludeVersion;
     std::string windowsSDKLibVersion;
-    if (llvm::getWindowsSDKDir(getVFS(), WinSdkDir, WinSdkVersion, WinSysRoot,
-                               WindowsSDKDir, major, windowsSDKIncludeVersion,
-                               windowsSDKLibVersion)) {
+    if (getWindowsSDKDir(getVFS(), DriverArgs, WindowsSDKDir, major,
+                         windowsSDKIncludeVersion, windowsSDKLibVersion)) {
       if (major >= 8) {
         // Note: windowsSDKIncludeVersion is empty for SDKs prior to v10.
         // Anyway, llvm::sys::path::append is able to manage it.
@@ -732,8 +1389,7 @@ VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D,
   if (MSVT.empty())
     MSVT = getTriple().getEnvironmentVersion();
   if (MSVT.empty() && IsWindowsMSVC)
-    MSVT =
-        getMSVCVersionFromExe(getSubDirectoryPath(llvm::SubDirectoryType::Bin));
+    MSVT = getMSVCVersionFromExe(getSubDirectoryPath(SubDirectoryType::Bin));
   if (MSVT.empty() &&
       Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
                    IsWindowsMSVC)) {

diff  --git a/clang/lib/Driver/ToolChains/MSVC.h b/clang/lib/Driver/ToolChains/MSVC.h
index 57be67e848e5b..c842773996eda 100644
--- a/clang/lib/Driver/ToolChains/MSVC.h
+++ b/clang/lib/Driver/ToolChains/MSVC.h
@@ -15,7 +15,6 @@
 #include "clang/Driver/Compilation.h"
 #include "clang/Driver/Tool.h"
 #include "clang/Driver/ToolChain.h"
-#include "llvm/WindowsDriver/MSVCPaths.h"
 
 namespace clang {
 namespace driver {
@@ -74,15 +73,29 @@ class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public ToolChain {
     return 4;
   }
 
-  std::string getSubDirectoryPath(llvm::SubDirectoryType Type,
-                                  llvm::StringRef SubdirParent = "") const;
-  std::string getSubDirectoryPath(llvm::SubDirectoryType Type,
+  enum class SubDirectoryType {
+    Bin,
+    Include,
+    Lib,
+  };
+  std::string getSubDirectoryPath(SubDirectoryType Type,
+                                  llvm::StringRef SubdirParent,
                                   llvm::Triple::ArchType TargetArch) const;
 
-  bool getIsVS2017OrNewer() const {
-    return VSLayout == llvm::ToolsetLayout::VS2017OrNewer;
+  // Convenience overload.
+  // Uses the current target arch.
+  std::string getSubDirectoryPath(SubDirectoryType Type,
+                                  llvm::StringRef SubdirParent = "") const {
+    return getSubDirectoryPath(Type, SubdirParent, getArch());
   }
 
+  enum class ToolsetLayout {
+    OlderVS,
+    VS2017OrNewer,
+    DevDivInternal,
+  };
+  bool getIsVS2017OrNewer() const { return VSLayout == ToolsetLayout::VS2017OrNewer; }
+
   void
   AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
                             llvm::opt::ArgStringList &CC1Args) const override;
@@ -129,9 +142,8 @@ class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public ToolChain {
   Tool *buildLinker() const override;
   Tool *buildAssembler() const override;
 private:
-  llvm::StringRef WinSdkDir, WinSdkVersion, WinSysRoot;
   std::string VCToolChainPath;
-  llvm::ToolsetLayout VSLayout = llvm::ToolsetLayout::OlderVS;
+  ToolsetLayout VSLayout = ToolsetLayout::OlderVS;
   CudaInstallationDetector CudaInstallation;
   RocmInstallationDetector RocmInstallation;
 };

diff  --git a/llvm/include/llvm/WindowsDriver/MSVCSetupApi.h b/clang/lib/Driver/ToolChains/MSVCSetupApi.h
similarity index 100%
rename from llvm/include/llvm/WindowsDriver/MSVCSetupApi.h
rename to clang/lib/Driver/ToolChains/MSVCSetupApi.h

diff  --git a/lld/COFF/CMakeLists.txt b/lld/COFF/CMakeLists.txt
index d289bd5910348..b32b9cfcff04e 100644
--- a/lld/COFF/CMakeLists.txt
+++ b/lld/COFF/CMakeLists.txt
@@ -38,7 +38,6 @@ add_lld_library(lldCOFF
   Option
   Passes
   Support
-  WindowsDriver
   WindowsManifest
 
   LINK_LIBS

diff  --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index f72b80c81e2d6..1546291e16c6b 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -24,7 +24,6 @@
 #include "lld/Common/Version.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
 #include "llvm/BinaryFormat/Magic.h"
 #include "llvm/Config/llvm-config.h"
 #include "llvm/LTO/LTO.h"
@@ -151,21 +150,6 @@ static StringRef mangle(StringRef sym) {
   return sym;
 }
 
-static llvm::Triple::ArchType getArch() {
-  switch (config->machine) {
-  case I386:
-    return llvm::Triple::ArchType::x86;
-  case AMD64:
-    return llvm::Triple::ArchType::x86_64;
-  case ARMNT:
-    return llvm::Triple::ArchType::arm;
-  case ARM64:
-    return llvm::Triple::ArchType::aarch64;
-  default:
-    return llvm::Triple::ArchType::UnknownArch;
-  }
-}
-
 bool LinkerDriver::findUnderscoreMangle(StringRef sym) {
   Symbol *s = ctx.symtab.findMangle(mangle(sym));
   return s && !isa<Undefined>(s);
@@ -520,101 +504,6 @@ Optional<StringRef> LinkerDriver::findLib(StringRef filename) {
   return path;
 }
 
-void LinkerDriver::detectWinSysRoot(const opt::InputArgList &Args) {
-  IntrusiveRefCntPtr<vfs::FileSystem> VFS = vfs::getRealFileSystem();
-
-  // 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.
-  StringRef VCToolsDir, VCToolsVersion, WinSysRoot;
-  if (auto *A = Args.getLastArg(OPT_vctoolsdir))
-    VCToolsDir = A->getValue();
-  if (auto *A = Args.getLastArg(OPT_vctoolsversion))
-    VCToolsVersion = A->getValue();
-  if (auto *A = Args.getLastArg(OPT_winsysroot))
-    WinSysRoot = A->getValue();
-  if (!findVCToolChainViaCommandLine(*VFS, VCToolsDir, VCToolsVersion,
-                                     WinSysRoot, vcToolChainPath, vsLayout) &&
-      (Args.hasArg(OPT_lldignoreenv) ||
-       !findVCToolChainViaEnvironment(*VFS, vcToolChainPath, vsLayout)) &&
-      !findVCToolChainViaSetupConfig(*VFS, vcToolChainPath, vsLayout) &&
-      !findVCToolChainViaRegistry(vcToolChainPath, vsLayout))
-    return;
-
-  // 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 auto *A = Args.getLastArg(OPT_diasdkdir, OPT_winsysroot)) {
-    diaPath = A->getValue();
-    if (A->getOption().getID() == OPT_winsysroot)
-      path::append(diaPath, "DIA SDK");
-  }
-  useWinSysRootLibPath = Args.hasArg(OPT_lldignoreenv) ||
-                         !Process::GetEnv("LIB") ||
-                         Args.getLastArg(OPT_vctoolsdir, OPT_winsysroot);
-  if (Args.hasArg(OPT_lldignoreenv) || !Process::GetEnv("LIB") ||
-      Args.getLastArg(OPT_winsdkdir, OPT_winsysroot)) {
-    StringRef WinSdkDir, WinSdkVersion;
-    if (auto *A = Args.getLastArg(OPT_winsdkdir))
-      WinSdkDir = A->getValue();
-    if (auto *A = Args.getLastArg(OPT_winsdkversion))
-      WinSdkVersion = A->getValue();
-
-    if (useUniversalCRT(vsLayout, vcToolChainPath, getArch(), *VFS)) {
-      std::string UniversalCRTSdkPath;
-      std::string UCRTVersion;
-      if (getUniversalCRTSdkDir(*VFS, WinSdkDir, WinSdkVersion, WinSysRoot,
-                                UniversalCRTSdkPath, UCRTVersion)) {
-        universalCRTLibPath = UniversalCRTSdkPath;
-        path::append(universalCRTLibPath, "Lib", UCRTVersion, "ucrt");
-      }
-    }
-
-    std::string sdkPath;
-    std::string windowsSDKIncludeVersion;
-    std::string windowsSDKLibVersion;
-    if (getWindowsSDKDir(*VFS, WinSdkDir, WinSdkVersion, WinSysRoot, sdkPath,
-                         sdkMajor, windowsSDKIncludeVersion,
-                         windowsSDKLibVersion)) {
-      windowsSdkLibPath = sdkPath;
-      path::append(windowsSdkLibPath, "Lib");
-      if (sdkMajor >= 8)
-        path::append(windowsSdkLibPath, windowsSDKLibVersion, "um");
-    }
-  }
-}
-
-void LinkerDriver::addWinSysRootLibSearchPaths() {
-  if (!diaPath.empty()) {
-    // The DIA SDK always uses the legacy vc arch, even in new MSVC versions.
-    path::append(diaPath, "lib", archToLegacyVCArch(getArch()));
-    searchPaths.push_back(saver().save(diaPath.str()));
-  }
-  if (useWinSysRootLibPath) {
-    searchPaths.push_back(saver().save(getSubDirectoryPath(
-        SubDirectoryType::Lib, vsLayout, vcToolChainPath, getArch())));
-    searchPaths.push_back(saver().save(
-        getSubDirectoryPath(SubDirectoryType::Lib, vsLayout, vcToolChainPath,
-                            getArch(), "atlmfc")));
-  }
-  if (!universalCRTLibPath.empty()) {
-    StringRef ArchName = archToWindowsSDKArch(getArch());
-    if (!ArchName.empty()) {
-      path::append(universalCRTLibPath, ArchName);
-      searchPaths.push_back(saver().save(universalCRTLibPath.str()));
-    }
-  }
-  if (!windowsSdkLibPath.empty()) {
-    std::string path;
-    if (appendArchToWindowsSDKLibPath(sdkMajor, windowsSdkLibPath, getArch(),
-                                      path))
-      searchPaths.push_back(saver().save(path));
-  }
-}
-
 // Parses LIB environment which contains a list of search paths.
 void LinkerDriver::addLibSearchPaths() {
   Optional<std::string> envOpt = Process::GetEnv("LIB");
@@ -737,7 +626,6 @@ static std::string createResponseFile(const opt::InputArgList &args,
     case OPT_INPUT:
     case OPT_defaultlib:
     case OPT_libpath:
-    case OPT_winsysroot:
       break;
     case OPT_call_graph_ordering_file:
     case OPT_deffile:
@@ -1447,8 +1335,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   searchPaths.push_back("");
   for (auto *arg : args.filtered(OPT_libpath))
     searchPaths.push_back(arg->getValue());
-  detectWinSysRoot(args);
-  if (!args.hasArg(OPT_lldignoreenv) && !args.hasArg(OPT_winsysroot))
+  if (!args.hasArg(OPT_lldignoreenv))
     addLibSearchPaths();
 
   // Handle /ignore
@@ -1588,7 +1475,6 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
     config->machine = getMachineType(arg->getValue());
     if (config->machine == IMAGE_FILE_MACHINE_UNKNOWN)
       fatal(Twine("unknown /machine argument: ") + arg->getValue());
-    addWinSysRootLibSearchPaths();
   }
 
   // Handle /nodefaultlib:<filename>
@@ -1950,8 +1836,15 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
     }
   }
 
+  // Process files specified as /defaultlib. These should be enequeued after
+  // other files, which is why they are in a separate loop.
+  for (auto *arg : args.filtered(OPT_defaultlib))
+    if (Optional<StringRef> path = findLib(arg->getValue()))
+      enqueuePath(*path, false, false);
+
   // Read all input files given via the command line.
   run();
+
   if (errorCount())
     return;
 
@@ -1960,19 +1853,9 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   if (config->machine == IMAGE_FILE_MACHINE_UNKNOWN) {
     warn("/machine is not specified. x64 is assumed");
     config->machine = AMD64;
-    addWinSysRootLibSearchPaths();
   }
   config->wordsize = config->is64() ? 8 : 4;
 
-  // Process files specified as /defaultlib. These must be processed after
-  // addWinSysRootLibSearchPaths(), which is why they are in a separate loop.
-  for (auto *arg : args.filtered(OPT_defaultlib))
-    if (Optional<StringRef> path = findLib(arg->getValue()))
-      enqueuePath(*path, false, false);
-  run();
-  if (errorCount())
-    return;
-
   // Handle /safeseh, x86 only, on by default, except for mingw.
   if (config->machine == I386) {
     config->safeSEH = args.hasFlag(OPT_safeseh, OPT_safeseh_no, !config->mingw);
@@ -1983,11 +1866,10 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   for (auto *arg : args.filtered(OPT_functionpadmin, OPT_functionpadmin_opt))
     parseFunctionPadMin(arg, config->machine);
 
-  if (tar) {
+  if (tar)
     tar->append("response.txt",
                 createResponseFile(args, filePaths,
                                    ArrayRef<StringRef>(searchPaths).slice(1)));
-  }
 
   // Handle /largeaddressaware
   config->largeAddressAware = args.hasFlag(

diff  --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h
index 162517340e80b..518ec1470677d 100644
--- a/lld/COFF/Driver.h
+++ b/lld/COFF/Driver.h
@@ -23,7 +23,6 @@
 #include "llvm/Option/ArgList.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/TarWriter.h"
-#include "llvm/WindowsDriver/MSVCPaths.h"
 #include <memory>
 #include <set>
 #include <vector>
@@ -83,10 +82,6 @@ class LinkerDriver {
 
   void linkerMain(llvm::ArrayRef<const char *> args);
 
-  // Adds various search paths based on the sysroot.  Must only be called once
-  // config->machine has been set.
-  void addWinSysRootLibSearchPaths();
-
   // Used by the resolver to parse .drectve section contents.
   void parseDirectives(InputFile *file);
 
@@ -112,9 +107,6 @@ class LinkerDriver {
 
   bool findUnderscoreMangle(StringRef sym);
 
-  // Determines the location of the sysroot based on `args`, environment, etc.
-  void detectWinSysRoot(const llvm::opt::InputArgList &args);
-
   // Parses LIB environment which contains a list of search paths.
   void addLibSearchPaths();
 
@@ -162,14 +154,6 @@ class LinkerDriver {
   llvm::StringSet<> directivesExports;
 
   COFFLinkerContext &ctx;
-
-  llvm::ToolsetLayout vsLayout = llvm::ToolsetLayout::OlderVS;
-  std::string vcToolChainPath;
-  llvm::SmallString<128> diaPath;
-  bool useWinSysRootLibPath = false;
-  llvm::SmallString<128> universalCRTLibPath;
-  int sdkMajor = 0;
-  llvm::SmallString<128> windowsSdkLibPath;
 };
 
 // Functions below this line are defined in DriverUtils.cpp.

diff  --git a/lld/COFF/Options.td b/lld/COFF/Options.td
index 7593b99dc05a7..7189088f8be6f 100644
--- a/lld/COFF/Options.td
+++ b/lld/COFF/Options.td
@@ -41,7 +41,6 @@ def color_diagnostics_eq: Joined<["--"], "color-diagnostics=">,
     MetaVarName<"[auto,always,never]">;
 def defaultlib : P<"defaultlib", "Add the library to the list of input files">;
 def delayload : P<"delayload", "Delay loaded DLL name">;
-def diasdkdir : P<"diasdkdir", "Set the location of the DIA SDK">;
 def entry   : P<"entry", "Name of entry point symbol">;
 def errorlimit : P<"errorlimit",
     "Maximum number of errors to emit before stopping (0 = no limit)">;
@@ -90,16 +89,9 @@ def stack   : P<"stack", "Size of the stack">;
 def stub    : P<"stub", "Specify DOS stub file">;
 def subsystem : P<"subsystem", "Specify subsystem">;
 def timestamp : P<"timestamp", "Specify the PE header timestamp">;
-def vctoolsdir : P<"vctoolsdir", "Set the location of the VC tools">;
-def vctoolsversion : P<"vctoolsversion",
-    "Specify which VC tools version to use">;
 def version : P<"version", "Specify a version number in the PE header">;
 def wholearchive_file : P<"wholearchive",
     "Include all object files from this library">;
-def winsdkdir : P<"winsdkdir", "Set the location of the Windows SDK">;
-def winsdkversion : P<"winsdkversion", "Specify which SDK version to use">;
-def winsysroot : P<"winsysroot",
-    "Adds several subdirectories to the library search paths">;
 
 def disallowlib : Joined<["/", "-", "/?", "-?"], "disallowlib:">,
     Alias<nodefaultlib>;

diff  --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index 9bd93a2ff1a7d..db2db9c9272eb 100644
--- a/lld/COFF/SymbolTable.cpp
+++ b/lld/COFF/SymbolTable.cpp
@@ -56,7 +56,6 @@ void SymbolTable::addFile(InputFile *file) {
   MachineTypes mt = file->getMachineType();
   if (config->machine == IMAGE_FILE_MACHINE_UNKNOWN) {
     config->machine = mt;
-    driver->addWinSysRootLibSearchPaths();
   } else if (mt != IMAGE_FILE_MACHINE_UNKNOWN && config->machine != mt) {
     error(toString(file) + ": machine type " + machineToStr(mt) +
           " conflicts with " + machineToStr(config->machine));

diff  --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst
index af09e1e539b87..1a31c13eb8905 100644
--- a/lld/docs/ReleaseNotes.rst
+++ b/lld/docs/ReleaseNotes.rst
@@ -36,9 +36,6 @@ Breaking changes
 COFF Improvements
 -----------------
 
-* Added autodetection of MSVC toolchain, a la clang-cl.  Also added /winsysroot
-  support for explicit specification of MSVC toolchain location.
-  (`D118070 <https://reviews.llvm.org/D118070>`_)
 * ...
 
 MinGW Improvements

diff  --git a/lld/test/COFF/winsysroot.test b/lld/test/COFF/winsysroot.test
deleted file mode 100644
index 5abcbce3548e9..0000000000000
--- a/lld/test/COFF/winsysroot.test
+++ /dev/null
@@ -1,17 +0,0 @@
-Check that /winsysroot results in the correct machine-specific subdirectory
-being searched for the defaultlibs, for a 32-bit .obj.
-# RUN: yaml2obj %p/Inputs/hello32.yaml -o %t.obj
-# RUN: mkdir -p %t.dir/sysroot/VC/Tools/MSVC/1.1.1.1/lib/x86
-# RUN: mkdir -p %t.dir/sysroot/VC/Tools/MSVC/1.1.1.1/lib/x64
-# RUN: cp %p/Inputs/std32.lib %t.dir/sysroot/VC/Tools/MSVC/1.1.1.1/lib/x86
-# RUN: cp %p/Inputs/std64.lib %t.dir/sysroot/VC/Tools/MSVC/1.1.1.1/lib/x64
-# RUN: not lld-link %t.obj /winsysroot:%t.dir/sysroot /defaultlib:std32 2>&1 | FileCheck -check-prefix=MISSINGENTRY32 --implicit-check-not=_ExitProcess %s
-MISSINGENTRY32: undefined symbol: _mainCRTStartup
-
-Check the same for a 64-bit input .obj.
-# RUN: not lld-link %p/Inputs/hello64.obj /winsysroot:%t.dir/sysroot /defaultlib:std64 2>&1 | FileCheck -check-prefix=MISSINGENTRY64 --implicit-check-not=_ExitProcess %s
-MISSINGENTRY64: undefined symbol: mainCRTStartup
-
-Check that when /winsysroot is specified, %LIB% is ignored.
-# RUN: env LIB=foo.dir/sysroot/VC/Tools/MSVC/1.1.1.1/lib/x86 not lld-link %t.obj /winsysroot:%t.dir/doesnotexist /defaultlib:std32 2>&1 | FileCheck -check-prefix=LIBIGNORED %s
-LIBIGNORED: could not open 'std32.lib'

diff  --git a/llvm/include/llvm/WindowsDriver/MSVCPaths.h b/llvm/include/llvm/WindowsDriver/MSVCPaths.h
deleted file mode 100644
index cadc872654b9e..0000000000000
--- a/llvm/include/llvm/WindowsDriver/MSVCPaths.h
+++ /dev/null
@@ -1,99 +0,0 @@
-//===-- MSVCPaths.h - MSVC path-parsing helpers -----------------*- 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_SUPPORT_MSVCPATHS_H
-#define LLVM_SUPPORT_MSVCPATHS_H
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Option/ArgList.h"
-#include "llvm/Support/VirtualFileSystem.h"
-#include <string>
-
-namespace llvm {
-
-enum class SubDirectoryType {
-  Bin,
-  Include,
-  Lib,
-};
-
-enum class ToolsetLayout {
-  OlderVS,
-  VS2017OrNewer,
-  DevDivInternal,
-};
-
-// Windows SDKs and VC Toolchains group their contents into subdirectories based
-// on the target architecture. This function converts an llvm::Triple::ArchType
-// to the corresponding subdirectory name.
-const char *archToWindowsSDKArch(llvm::Triple::ArchType Arch);
-
-// Similar to the above function, but for Visual Studios before VS2017.
-const char *archToLegacyVCArch(llvm::Triple::ArchType Arch);
-
-// Similar to the above function, but for DevDiv internal builds.
-const char *archToDevDivInternalArch(llvm::Triple::ArchType Arch);
-
-bool appendArchToWindowsSDKLibPath(int SDKMajor, llvm::SmallString<128> LibPath,
-                                   llvm::Triple::ArchType Arch,
-                                   std::string &path);
-
-// Get the path to a specific subdirectory in the current toolchain for
-// a given target architecture.
-// VS2017 changed the VC toolchain layout, so this should be used instead
-// of hardcoding paths.
-std::string getSubDirectoryPath(SubDirectoryType Type, ToolsetLayout VSLayout,
-                                const std::string &VCToolChainPath,
-                                llvm::Triple::ArchType TargetArch,
-                                llvm::StringRef SubdirParent = "");
-
-// Check if the Include path of a specified version of Visual Studio contains
-// specific header files. If not, they are probably shipped with Universal CRT.
-bool useUniversalCRT(ToolsetLayout VSLayout, const std::string &VCToolChainPath,
-                     llvm::Triple::ArchType TargetArch,
-                     llvm::vfs::FileSystem &VFS);
-
-/// Get Windows SDK installation directory.
-bool getWindowsSDKDir(vfs::FileSystem &VFS, llvm::StringRef WinSdkDir,
-                      llvm::StringRef WinSdkVersion, llvm::StringRef WinSysRoot,
-                      std::string &Path, int &Major,
-                      std::string &WindowsSDKIncludeVersion,
-                      std::string &WindowsSDKLibVersion);
-
-bool getUniversalCRTSdkDir(vfs::FileSystem &VFS, llvm::StringRef WinSdkDir,
-                           llvm::StringRef WinSdkVersion,
-                           llvm::StringRef WinSysRoot, std::string &Path,
-                           std::string &UCRTVersion);
-
-// Check command line arguments to try and find a toolchain.
-bool findVCToolChainViaCommandLine(vfs::FileSystem &VFS,
-                                   llvm::StringRef VCToolsDir,
-                                   llvm::StringRef VCToolsVersion,
-                                   llvm::StringRef WinSysRoot,
-                                   std::string &Path, ToolsetLayout &VSLayout);
-
-// Check various environment variables to try and find a toolchain.
-bool findVCToolChainViaEnvironment(vfs::FileSystem &VFS, std::string &Path,
-                                   ToolsetLayout &VSLayout);
-
-// Query the Setup Config server for installs, then pick the newest version
-// and find its default VC toolchain.
-// This is the preferred way to discover new Visual Studios, as they're no
-// longer listed in the registry.
-bool findVCToolChainViaSetupConfig(vfs::FileSystem &VFS, std::string &Path,
-                                   ToolsetLayout &VSLayout);
-
-// Look in the registry for Visual Studio installs, and use that to get
-// a toolchain path. VS2017 and newer don't get added to the registry.
-// So if we find something here, we know that it's an older version.
-bool findVCToolChainViaRegistry(std::string &Path, ToolsetLayout &VSLayout);
-
-} // namespace llvm
-
-#endif

diff  --git a/llvm/lib/CMakeLists.txt b/llvm/lib/CMakeLists.txt
index 57bf209a67699..68236c34bf614 100644
--- a/llvm/lib/CMakeLists.txt
+++ b/llvm/lib/CMakeLists.txt
@@ -40,7 +40,6 @@ add_subdirectory(XRay)
 if (LLVM_INCLUDE_TESTS)
   add_subdirectory(Testing)
 endif()
-add_subdirectory(WindowsDriver)
 add_subdirectory(WindowsManifest)
 
 set(LLVMCONFIGLIBRARYDEPENDENCIESINC "${LLVM_BINARY_DIR}/tools/llvm-config/LibraryDependencies.inc")

diff  --git a/llvm/lib/WindowsDriver/CMakeLists.txt b/llvm/lib/WindowsDriver/CMakeLists.txt
deleted file mode 100644
index 6d61feecc107d..0000000000000
--- a/llvm/lib/WindowsDriver/CMakeLists.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-add_llvm_component_library(LLVMWindowsDriver
-  MSVCPaths.cpp
-
-  ADDITIONAL_HEADER_DIRS
-  ${LLVM_MAIN_INCLUDE_DIR}/llvm/WindowsDriver
-
-  LINK_LIBS
-  ${imported_libs}
-
-  LINK_COMPONENTS
-  Option
-  Support
-  )

diff  --git a/llvm/lib/WindowsDriver/MSVCPaths.cpp b/llvm/lib/WindowsDriver/MSVCPaths.cpp
deleted file mode 100644
index 0d41484a1abfb..0000000000000
--- a/llvm/lib/WindowsDriver/MSVCPaths.cpp
+++ /dev/null
@@ -1,709 +0,0 @@
-//===-- MSVCPaths.cpp - MSVC path-parsing helpers -------------------------===//
-//
-// 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 "llvm/WindowsDriver/MSVCPaths.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Option/Arg.h"
-#include "llvm/Option/ArgList.h"
-#include "llvm/Support/ConvertUTF.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/Process.h"
-#include "llvm/Support/Program.h"
-#include "llvm/Support/VersionTuple.h"
-#include "llvm/Support/VirtualFileSystem.h"
-#include <string>
-
-#ifdef _WIN32
-#define WIN32_LEAN_AND_MEAN
-#define NOGDI
-#ifndef NOMINMAX
-#define NOMINMAX
-#endif
-#include <windows.h>
-#endif
-
-#ifdef _MSC_VER
-// Don't support SetupApi on MinGW.
-#define USE_MSVC_SETUP_API
-
-// Make sure this comes before MSVCSetupApi.h
-#include <comdef.h>
-
-#include "llvm/Support/COM.h"
-#ifdef __clang__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
-#endif
-#include "llvm/WindowsDriver/MSVCSetupApi.h"
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif
-_COM_SMARTPTR_TYPEDEF(ISetupConfiguration, __uuidof(ISetupConfiguration));
-_COM_SMARTPTR_TYPEDEF(ISetupConfiguration2, __uuidof(ISetupConfiguration2));
-_COM_SMARTPTR_TYPEDEF(ISetupHelper, __uuidof(ISetupHelper));
-_COM_SMARTPTR_TYPEDEF(IEnumSetupInstances, __uuidof(IEnumSetupInstances));
-_COM_SMARTPTR_TYPEDEF(ISetupInstance, __uuidof(ISetupInstance));
-_COM_SMARTPTR_TYPEDEF(ISetupInstance2, __uuidof(ISetupInstance2));
-#endif
-
-static std::string
-getHighestNumericTupleInDirectory(llvm::vfs::FileSystem &VFS,
-                                  llvm::StringRef Directory) {
-  std::string Highest;
-  llvm::VersionTuple HighestTuple;
-
-  std::error_code EC;
-  for (llvm::vfs::directory_iterator DirIt = VFS.dir_begin(Directory, EC),
-                                     DirEnd;
-       !EC && DirIt != DirEnd; DirIt.increment(EC)) {
-    auto Status = VFS.status(DirIt->path());
-    if (!Status || !Status->isDirectory())
-      continue;
-    llvm::StringRef CandidateName = llvm::sys::path::filename(DirIt->path());
-    llvm::VersionTuple Tuple;
-    if (Tuple.tryParse(CandidateName)) // tryParse() returns true on error.
-      continue;
-    if (Tuple > HighestTuple) {
-      HighestTuple = Tuple;
-      Highest = CandidateName.str();
-    }
-  }
-
-  return Highest;
-}
-
-static bool getWindows10SDKVersionFromPath(llvm::vfs::FileSystem &VFS,
-                                           const std::string &SDKPath,
-                                           std::string &SDKVersion) {
-  llvm::SmallString<128> IncludePath(SDKPath);
-  llvm::sys::path::append(IncludePath, "Include");
-  SDKVersion = getHighestNumericTupleInDirectory(VFS, IncludePath);
-  return !SDKVersion.empty();
-}
-
-static bool getWindowsSDKDirViaCommandLine(llvm::vfs::FileSystem &VFS,
-                                           llvm::StringRef WinSdkDir,
-                                           llvm::StringRef WinSdkVersion,
-                                           llvm::StringRef WinSysRoot,
-                                           std::string &Path, int &Major,
-                                           std::string &Version) {
-  if (!WinSdkDir.empty() || !WinSysRoot.empty()) {
-    // Don't validate the input; trust the value supplied by the user.
-    // The motivation is to prevent unnecessary file and registry access.
-    llvm::VersionTuple SDKVersion;
-    if (!WinSdkVersion.empty())
-      SDKVersion.tryParse(WinSdkVersion);
-
-    if (!WinSysRoot.empty()) {
-      llvm::SmallString<128> SDKPath(WinSysRoot);
-      llvm::sys::path::append(SDKPath, "Windows Kits");
-      if (!SDKVersion.empty())
-        llvm::sys::path::append(SDKPath, llvm::Twine(SDKVersion.getMajor()));
-      else
-        llvm::sys::path::append(
-            SDKPath, getHighestNumericTupleInDirectory(VFS, SDKPath));
-      Path = std::string(SDKPath.str());
-    } else {
-      Path = WinSdkDir.str();
-    }
-
-    if (!SDKVersion.empty()) {
-      Major = SDKVersion.getMajor();
-      Version = SDKVersion.getAsString();
-    } else if (getWindows10SDKVersionFromPath(VFS, Path, Version)) {
-      Major = 10;
-    }
-    return true;
-  }
-  return false;
-}
-
-#ifdef _WIN32
-static bool readFullStringValue(HKEY hkey, const char *valueName,
-                                std::string &value) {
-  std::wstring WideValueName;
-  if (!llvm::ConvertUTF8toWide(valueName, WideValueName))
-    return false;
-
-  DWORD result = 0;
-  DWORD valueSize = 0;
-  DWORD type = 0;
-  // First just query for the required size.
-  result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, &type, NULL,
-                            &valueSize);
-  if (result != ERROR_SUCCESS || type != REG_SZ || !valueSize)
-    return false;
-  std::vector<BYTE> buffer(valueSize);
-  result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, NULL, &buffer[0],
-                            &valueSize);
-  if (result == ERROR_SUCCESS) {
-    std::wstring WideValue(reinterpret_cast<const wchar_t *>(buffer.data()),
-                           valueSize / sizeof(wchar_t));
-    if (valueSize && WideValue.back() == L'\0') {
-      WideValue.pop_back();
-    }
-    // The destination buffer must be empty as an invariant of the conversion
-    // function; but this function is sometimes called in a loop that passes in
-    // the same buffer, however. Simply clear it out so we can overwrite it.
-    value.clear();
-    return llvm::convertWideToUTF8(WideValue, value);
-  }
-  return false;
-}
-#endif
-
-/// Read registry string.
-/// This also supports a means to look for high-versioned keys by use
-/// of a $VERSION placeholder in the key path.
-/// $VERSION in the key path is a placeholder for the version number,
-/// causing the highest value path to be searched for and used.
-/// I.e. "SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
-/// There can be additional characters in the component.  Only the numeric
-/// characters are compared.  This function only searches HKLM.
-static bool getSystemRegistryString(const char *keyPath, const char *valueName,
-                                    std::string &value, std::string *phValue) {
-#ifndef _WIN32
-  return false;
-#else
-  HKEY hRootKey = HKEY_LOCAL_MACHINE;
-  HKEY hKey = NULL;
-  long lResult;
-  bool returnValue = false;
-
-  const char *placeHolder = strstr(keyPath, "$VERSION");
-  std::string bestName;
-  // If we have a $VERSION placeholder, do the highest-version search.
-  if (placeHolder) {
-    const char *keyEnd = placeHolder - 1;
-    const char *nextKey = placeHolder;
-    // Find end of previous key.
-    while ((keyEnd > keyPath) && (*keyEnd != '\\'))
-      keyEnd--;
-    // Find end of key containing $VERSION.
-    while (*nextKey && (*nextKey != '\\'))
-      nextKey++;
-    size_t partialKeyLength = keyEnd - keyPath;
-    char partialKey[256];
-    if (partialKeyLength >= sizeof(partialKey))
-      partialKeyLength = sizeof(partialKey) - 1;
-    strncpy(partialKey, keyPath, partialKeyLength);
-    partialKey[partialKeyLength] = '\0';
-    HKEY hTopKey = NULL;
-    lResult = RegOpenKeyExA(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY,
-                            &hTopKey);
-    if (lResult == ERROR_SUCCESS) {
-      char keyName[256];
-      double bestValue = 0.0;
-      DWORD index, size = sizeof(keyName) - 1;
-      for (index = 0; RegEnumKeyExA(hTopKey, index, keyName, &size, NULL, NULL,
-                                    NULL, NULL) == ERROR_SUCCESS;
-           index++) {
-        const char *sp = keyName;
-        while (*sp && !llvm::isDigit(*sp))
-          sp++;
-        if (!*sp)
-          continue;
-        const char *ep = sp + 1;
-        while (*ep && (llvm::isDigit(*ep) || (*ep == '.')))
-          ep++;
-        char numBuf[32];
-        strncpy(numBuf, sp, sizeof(numBuf) - 1);
-        numBuf[sizeof(numBuf) - 1] = '\0';
-        double dvalue = strtod(numBuf, NULL);
-        if (dvalue > bestValue) {
-          // Test that InstallDir is indeed there before keeping this index.
-          // Open the chosen key path remainder.
-          bestName = keyName;
-          // Append rest of key.
-          bestName.append(nextKey);
-          lResult = RegOpenKeyExA(hTopKey, bestName.c_str(), 0,
-                                  KEY_READ | KEY_WOW64_32KEY, &hKey);
-          if (lResult == ERROR_SUCCESS) {
-            if (readFullStringValue(hKey, valueName, value)) {
-              bestValue = dvalue;
-              if (phValue)
-                *phValue = bestName;
-              returnValue = true;
-            }
-            RegCloseKey(hKey);
-          }
-        }
-        size = sizeof(keyName) - 1;
-      }
-      RegCloseKey(hTopKey);
-    }
-  } else {
-    lResult =
-        RegOpenKeyExA(hRootKey, keyPath, 0, KEY_READ | KEY_WOW64_32KEY, &hKey);
-    if (lResult == ERROR_SUCCESS) {
-      if (readFullStringValue(hKey, valueName, value))
-        returnValue = true;
-      if (phValue)
-        phValue->clear();
-      RegCloseKey(hKey);
-    }
-  }
-  return returnValue;
-#endif // _WIN32
-}
-
-namespace llvm {
-
-const char *archToWindowsSDKArch(Triple::ArchType Arch) {
-  switch (Arch) {
-  case Triple::ArchType::x86:
-    return "x86";
-  case Triple::ArchType::x86_64:
-    return "x64";
-  case Triple::ArchType::arm:
-    return "arm";
-  case Triple::ArchType::aarch64:
-    return "arm64";
-  default:
-    return "";
-  }
-}
-
-const char *archToLegacyVCArch(Triple::ArchType Arch) {
-  switch (Arch) {
-  case Triple::ArchType::x86:
-    // x86 is default in legacy VC toolchains.
-    // e.g. x86 libs are directly in /lib as opposed to /lib/x86.
-    return "";
-  case Triple::ArchType::x86_64:
-    return "amd64";
-  case Triple::ArchType::arm:
-    return "arm";
-  case Triple::ArchType::aarch64:
-    return "arm64";
-  default:
-    return "";
-  }
-}
-
-const char *archToDevDivInternalArch(Triple::ArchType Arch) {
-  switch (Arch) {
-  case Triple::ArchType::x86:
-    return "i386";
-  case Triple::ArchType::x86_64:
-    return "amd64";
-  case Triple::ArchType::arm:
-    return "arm";
-  case Triple::ArchType::aarch64:
-    return "arm64";
-  default:
-    return "";
-  }
-}
-
-bool appendArchToWindowsSDKLibPath(int SDKMajor, SmallString<128> LibPath,
-                                   Triple::ArchType Arch, std::string &path) {
-  if (SDKMajor >= 8) {
-    sys::path::append(LibPath, archToWindowsSDKArch(Arch));
-  } else {
-    switch (Arch) {
-    // In Windows SDK 7.x, x86 libraries are directly in the Lib folder.
-    case Triple::x86:
-      break;
-    case Triple::x86_64:
-      sys::path::append(LibPath, "x64");
-      break;
-    case Triple::arm:
-      // It is not necessary to link against Windows SDK 7.x when targeting ARM.
-      return false;
-    default:
-      return false;
-    }
-  }
-
-  path = std::string(LibPath.str());
-  return true;
-}
-
-std::string getSubDirectoryPath(SubDirectoryType Type, ToolsetLayout VSLayout,
-                                const std::string &VCToolChainPath,
-                                Triple::ArchType TargetArch,
-                                StringRef SubdirParent) {
-  const char *SubdirName;
-  const char *IncludeName;
-  switch (VSLayout) {
-  case ToolsetLayout::OlderVS:
-    SubdirName = archToLegacyVCArch(TargetArch);
-    IncludeName = "include";
-    break;
-  case ToolsetLayout::VS2017OrNewer:
-    SubdirName = archToWindowsSDKArch(TargetArch);
-    IncludeName = "include";
-    break;
-  case ToolsetLayout::DevDivInternal:
-    SubdirName = archToDevDivInternalArch(TargetArch);
-    IncludeName = "inc";
-    break;
-  }
-
-  SmallString<256> Path(VCToolChainPath);
-  if (!SubdirParent.empty())
-    sys::path::append(Path, SubdirParent);
-
-  switch (Type) {
-  case SubDirectoryType::Bin:
-    if (VSLayout == ToolsetLayout::VS2017OrNewer) {
-      const bool HostIsX64 = Triple(sys::getProcessTriple()).isArch64Bit();
-      const char *const HostName = HostIsX64 ? "Hostx64" : "Hostx86";
-      sys::path::append(Path, "bin", HostName, SubdirName);
-    } else { // OlderVS or DevDivInternal
-      sys::path::append(Path, "bin", SubdirName);
-    }
-    break;
-  case SubDirectoryType::Include:
-    sys::path::append(Path, IncludeName);
-    break;
-  case SubDirectoryType::Lib:
-    sys::path::append(Path, "lib", SubdirName);
-    break;
-  }
-  return std::string(Path.str());
-}
-
-bool useUniversalCRT(ToolsetLayout VSLayout, const std::string &VCToolChainPath,
-                     Triple::ArchType TargetArch, vfs::FileSystem &VFS) {
-  SmallString<128> TestPath(getSubDirectoryPath(
-      SubDirectoryType::Include, VSLayout, VCToolChainPath, TargetArch));
-  sys::path::append(TestPath, "stdlib.h");
-  return !VFS.exists(TestPath);
-}
-
-bool getWindowsSDKDir(vfs::FileSystem &VFS, StringRef WinSdkDir,
-                      StringRef WinSdkVersion, StringRef WinSysRoot,
-                      std::string &Path, int &Major,
-                      std::string &WindowsSDKIncludeVersion,
-                      std::string &WindowsSDKLibVersion) {
-  // Trust /winsdkdir and /winsdkversion if present.
-  if (getWindowsSDKDirViaCommandLine(VFS, WinSdkDir, WinSdkVersion, WinSysRoot,
-                                     Path, Major, WindowsSDKIncludeVersion)) {
-    WindowsSDKLibVersion = WindowsSDKIncludeVersion;
-    return true;
-  }
-
-  // FIXME: Try env vars (%WindowsSdkDir%, %UCRTVersion%) before going to
-  // registry.
-
-  // Try the Windows registry.
-  std::string RegistrySDKVersion;
-  if (!getSystemRegistryString(
-          "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
-          "InstallationFolder", Path, &RegistrySDKVersion))
-    return false;
-  if (Path.empty() || RegistrySDKVersion.empty())
-    return false;
-
-  WindowsSDKIncludeVersion.clear();
-  WindowsSDKLibVersion.clear();
-  Major = 0;
-  std::sscanf(RegistrySDKVersion.c_str(), "v%d.", &Major);
-  if (Major <= 7)
-    return true;
-  if (Major == 8) {
-    // Windows SDK 8.x installs libraries in a folder whose names depend on the
-    // version of the OS you're targeting.  By default choose the newest, which
-    // usually corresponds to the version of the OS you've installed the SDK on.
-    const char *Tests[] = {"winv6.3", "win8", "win7"};
-    for (const char *Test : Tests) {
-      SmallString<128> TestPath(Path);
-      sys::path::append(TestPath, "Lib", Test);
-      if (VFS.exists(TestPath)) {
-        WindowsSDKLibVersion = Test;
-        break;
-      }
-    }
-    return !WindowsSDKLibVersion.empty();
-  }
-  if (Major == 10) {
-    if (!getWindows10SDKVersionFromPath(VFS, Path, WindowsSDKIncludeVersion))
-      return false;
-    WindowsSDKLibVersion = WindowsSDKIncludeVersion;
-    return true;
-  }
-  // Unsupported SDK version
-  return false;
-}
-
-bool getUniversalCRTSdkDir(vfs::FileSystem &VFS, StringRef WinSdkDir,
-                           StringRef WinSdkVersion, StringRef WinSysRoot,
-                           std::string &Path, std::string &UCRTVersion) {
-  // If /winsdkdir is passed, use it as location for the UCRT too.
-  // FIXME: Should there be a dedicated /ucrtdir to override /winsdkdir?
-  int Major;
-  if (getWindowsSDKDirViaCommandLine(VFS, WinSdkDir, WinSdkVersion, WinSysRoot,
-                                     Path, Major, UCRTVersion))
-    return true;
-
-  // FIXME: Try env vars (%UniversalCRTSdkDir%, %UCRTVersion%) before going to
-  // registry.
-
-  // vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry
-  // for the specific key "KitsRoot10". So do we.
-  if (!getSystemRegistryString(
-          "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10",
-          Path, nullptr))
-    return false;
-
-  return getWindows10SDKVersionFromPath(VFS, Path, UCRTVersion);
-}
-
-bool findVCToolChainViaCommandLine(vfs::FileSystem &VFS, StringRef VCToolsDir,
-                                   StringRef VCToolsVersion,
-                                   StringRef WinSysRoot, std::string &Path,
-                                   ToolsetLayout &VSLayout) {
-  // Don't validate the input; trust the value supplied by the user.
-  // The primary motivation is to prevent unnecessary file and registry access.
-  if (!VCToolsDir.empty() || !WinSysRoot.empty()) {
-    if (!WinSysRoot.empty()) {
-      SmallString<128> ToolsPath(WinSysRoot);
-      sys::path::append(ToolsPath, "VC", "Tools", "MSVC");
-      std::string ToolsVersion;
-      if (!VCToolsVersion.empty())
-        ToolsVersion = VCToolsVersion.str();
-      else
-        ToolsVersion = getHighestNumericTupleInDirectory(VFS, ToolsPath);
-      sys::path::append(ToolsPath, ToolsVersion);
-      Path = std::string(ToolsPath.str());
-    } else {
-      Path = VCToolsDir.str();
-    }
-    VSLayout = ToolsetLayout::VS2017OrNewer;
-    return true;
-  }
-  return false;
-}
-
-bool findVCToolChainViaEnvironment(vfs::FileSystem &VFS, std::string &Path,
-                                   ToolsetLayout &VSLayout) {
-  // These variables are typically set by vcvarsall.bat
-  // when launching a developer command prompt.
-  if (Optional<std::string> VCToolsInstallDir =
-          sys::Process::GetEnv("VCToolsInstallDir")) {
-    // This is only set by newer Visual Studios, and it leads straight to
-    // the toolchain directory.
-    Path = std::move(*VCToolsInstallDir);
-    VSLayout = ToolsetLayout::VS2017OrNewer;
-    return true;
-  }
-  if (Optional<std::string> VCInstallDir =
-          sys::Process::GetEnv("VCINSTALLDIR")) {
-    // If the previous variable isn't set but this one is, then we've found
-    // an older Visual Studio. This variable is set by newer Visual Studios too,
-    // so this check has to appear second.
-    // In older Visual Studios, the VC directory is the toolchain.
-    Path = std::move(*VCInstallDir);
-    VSLayout = ToolsetLayout::OlderVS;
-    return true;
-  }
-
-  // We couldn't find any VC environment variables. Let's walk through PATH and
-  // see if it leads us to a VC toolchain bin directory. If it does, pick the
-  // first one that we find.
-  if (Optional<std::string> PathEnv = sys::Process::GetEnv("PATH")) {
-    SmallVector<StringRef, 8> PathEntries;
-    StringRef(*PathEnv).split(PathEntries, sys::EnvPathSeparator);
-    for (StringRef PathEntry : PathEntries) {
-      if (PathEntry.empty())
-        continue;
-
-      SmallString<256> ExeTestPath;
-
-      // If cl.exe doesn't exist, then this definitely isn't a VC toolchain.
-      ExeTestPath = PathEntry;
-      sys::path::append(ExeTestPath, "cl.exe");
-      if (!VFS.exists(ExeTestPath))
-        continue;
-
-      // cl.exe existing isn't a conclusive test for a VC toolchain; clang also
-      // has a cl.exe. So let's check for link.exe too.
-      ExeTestPath = PathEntry;
-      sys::path::append(ExeTestPath, "link.exe");
-      if (!VFS.exists(ExeTestPath))
-        continue;
-
-      // whatever/VC/bin --> old toolchain, VC dir is toolchain dir.
-      StringRef TestPath = PathEntry;
-      bool IsBin = sys::path::filename(TestPath).equals_insensitive("bin");
-      if (!IsBin) {
-        // Strip any architecture subdir like "amd64".
-        TestPath = sys::path::parent_path(TestPath);
-        IsBin = sys::path::filename(TestPath).equals_insensitive("bin");
-      }
-      if (IsBin) {
-        StringRef ParentPath = sys::path::parent_path(TestPath);
-        StringRef ParentFilename = sys::path::filename(ParentPath);
-        if (ParentFilename.equals_insensitive("VC")) {
-          Path = std::string(ParentPath);
-          VSLayout = ToolsetLayout::OlderVS;
-          return true;
-        }
-        if (ParentFilename.equals_insensitive("x86ret") ||
-            ParentFilename.equals_insensitive("x86chk") ||
-            ParentFilename.equals_insensitive("amd64ret") ||
-            ParentFilename.equals_insensitive("amd64chk")) {
-          Path = std::string(ParentPath);
-          VSLayout = ToolsetLayout::DevDivInternal;
-          return true;
-        }
-
-      } else {
-        // This could be a new (>=VS2017) toolchain. If it is, we should find
-        // path components with these prefixes when walking backwards through
-        // the path.
-        // Note: empty strings match anything.
-        StringRef ExpectedPrefixes[] = {"",     "Host",  "bin", "",
-                                        "MSVC", "Tools", "VC"};
-
-        auto It = sys::path::rbegin(PathEntry);
-        auto End = sys::path::rend(PathEntry);
-        for (StringRef Prefix : ExpectedPrefixes) {
-          if (It == End)
-            goto NotAToolChain;
-          if (!It->startswith_insensitive(Prefix))
-            goto NotAToolChain;
-          ++It;
-        }
-
-        // We've found a new toolchain!
-        // Back up 3 times (/bin/Host/arch) to get the root path.
-        StringRef ToolChainPath(PathEntry);
-        for (int i = 0; i < 3; ++i)
-          ToolChainPath = sys::path::parent_path(ToolChainPath);
-
-        Path = std::string(ToolChainPath);
-        VSLayout = ToolsetLayout::VS2017OrNewer;
-        return true;
-      }
-
-    NotAToolChain:
-      continue;
-    }
-  }
-  return false;
-}
-
-bool findVCToolChainViaSetupConfig(vfs::FileSystem &VFS, std::string &Path,
-                                   ToolsetLayout &VSLayout) {
-#if !defined(USE_MSVC_SETUP_API)
-  return false;
-#else
-  // FIXME: This really should be done once in the top-level program's main
-  // function, as it may have already been initialized with a 
diff erent
-  // threading model otherwise.
-  sys::InitializeCOMRAII COM(sys::COMThreadingMode::SingleThreaded);
-  HRESULT HR;
-
-  // _com_ptr_t will throw a _com_error if a COM calls fail.
-  // The LLVM coding standards forbid exception handling, so we'll have to
-  // stop them from being thrown in the first place.
-  // The destructor will put the regular error handler back when we leave
-  // this scope.
-  struct SuppressCOMErrorsRAII {
-    static void __stdcall handler(HRESULT hr, IErrorInfo *perrinfo) {}
-
-    SuppressCOMErrorsRAII() { _set_com_error_handler(handler); }
-
-    ~SuppressCOMErrorsRAII() { _set_com_error_handler(_com_raise_error); }
-
-  } COMErrorSuppressor;
-
-  ISetupConfigurationPtr Query;
-  HR = Query.CreateInstance(__uuidof(SetupConfiguration));
-  if (FAILED(HR))
-    return false;
-
-  IEnumSetupInstancesPtr EnumInstances;
-  HR = ISetupConfiguration2Ptr(Query)->EnumAllInstances(&EnumInstances);
-  if (FAILED(HR))
-    return false;
-
-  ISetupInstancePtr Instance;
-  HR = EnumInstances->Next(1, &Instance, nullptr);
-  if (HR != S_OK)
-    return false;
-
-  ISetupInstancePtr NewestInstance;
-  Optional<uint64_t> NewestVersionNum;
-  do {
-    bstr_t VersionString;
-    uint64_t VersionNum;
-    HR = Instance->GetInstallationVersion(VersionString.GetAddress());
-    if (FAILED(HR))
-      continue;
-    HR = ISetupHelperPtr(Query)->ParseVersion(VersionString, &VersionNum);
-    if (FAILED(HR))
-      continue;
-    if (!NewestVersionNum || (VersionNum > NewestVersionNum)) {
-      NewestInstance = Instance;
-      NewestVersionNum = VersionNum;
-    }
-  } while ((HR = EnumInstances->Next(1, &Instance, nullptr)) == S_OK);
-
-  if (!NewestInstance)
-    return false;
-
-  bstr_t VCPathWide;
-  HR = NewestInstance->ResolvePath(L"VC", VCPathWide.GetAddress());
-  if (FAILED(HR))
-    return false;
-
-  std::string VCRootPath;
-  convertWideToUTF8(std::wstring(VCPathWide), VCRootPath);
-
-  SmallString<256> ToolsVersionFilePath(VCRootPath);
-  sys::path::append(ToolsVersionFilePath, "Auxiliary", "Build",
-                    "Microsoft.VCToolsVersion.default.txt");
-
-  auto ToolsVersionFile = MemoryBuffer::getFile(ToolsVersionFilePath);
-  if (!ToolsVersionFile)
-    return false;
-
-  SmallString<256> ToolchainPath(VCRootPath);
-  sys::path::append(ToolchainPath, "Tools", "MSVC",
-                    ToolsVersionFile->get()->getBuffer().rtrim());
-  auto Status = VFS.status(ToolchainPath);
-  if (!Status || !Status->isDirectory())
-    return false;
-
-  Path = std::string(ToolchainPath.str());
-  VSLayout = ToolsetLayout::VS2017OrNewer;
-  return true;
-#endif
-}
-
-bool findVCToolChainViaRegistry(std::string &Path, ToolsetLayout &VSLayout) {
-  std::string VSInstallPath;
-  if (getSystemRegistryString(R"(SOFTWARE\Microsoft\VisualStudio\$VERSION)",
-                              "InstallDir", VSInstallPath, nullptr) ||
-      getSystemRegistryString(R"(SOFTWARE\Microsoft\VCExpress\$VERSION)",
-                              "InstallDir", VSInstallPath, nullptr)) {
-    if (!VSInstallPath.empty()) {
-      SmallString<256> VCPath(StringRef(VSInstallPath.c_str(),
-                                        VSInstallPath.find(R"(\Common7\IDE)")));
-      sys::path::append(VCPath, "VC");
-
-      Path = std::string(VCPath.str());
-      VSLayout = ToolsetLayout::OlderVS;
-      return true;
-    }
-  }
-  return false;
-}
-
-} // namespace llvm

diff  --git a/llvm/utils/gn/secondary/clang/lib/Driver/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/Driver/BUILD.gn
index 2f89bd847e683..6e34fcc28c0a8 100644
--- a/llvm/utils/gn/secondary/clang/lib/Driver/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/lib/Driver/BUILD.gn
@@ -18,7 +18,6 @@ static_library("Driver") {
     "//llvm/lib/BinaryFormat",
     "//llvm/lib/Option",
     "//llvm/lib/Support",
-    "//llvm/lib/WindowsDriver",
   ]
   public_deps = [
     # public_dep because public header Options.h includes generated Options.inc.

diff  --git a/llvm/utils/gn/secondary/lld/COFF/BUILD.gn b/llvm/utils/gn/secondary/lld/COFF/BUILD.gn
index 97fc788e0ef96..57dd9dbbd2c10 100644
--- a/llvm/utils/gn/secondary/lld/COFF/BUILD.gn
+++ b/llvm/utils/gn/secondary/lld/COFF/BUILD.gn
@@ -23,7 +23,6 @@ static_library("COFF") {
     "//llvm/lib/Support",
     "//llvm/lib/Target:TargetsToBuild",
     "//llvm/lib/ToolDrivers/llvm-lib:LibDriver",
-    "//llvm/lib/WindowsDriver",
     "//llvm/lib/WindowsManifest",
   ]
   sources = [

diff  --git a/llvm/utils/gn/secondary/llvm/lib/WindowsDriver/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/WindowsDriver/BUILD.gn
deleted file mode 100644
index 12d8d299cda7c..0000000000000
--- a/llvm/utils/gn/secondary/llvm/lib/WindowsDriver/BUILD.gn
+++ /dev/null
@@ -1,8 +0,0 @@
-static_library("WindowsDriver") {
-  output_name = "LLVMWindowsDriver"
-  deps = [
-    "//llvm/lib/Option",
-    "//llvm/lib/Support",
-  ]
-  sources = [ "MSVCPaths.cpp" ]
-}


        


More information about the llvm-commits mailing list