summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Driver/MSVCToolChain.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver/MSVCToolChain.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/MSVCToolChain.cpp324
1 files changed, 269 insertions, 55 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/MSVCToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/MSVCToolChain.cpp
index c816b29..b7e576e 100644
--- a/contrib/llvm/tools/clang/lib/Driver/MSVCToolChain.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/MSVCToolChain.cpp
@@ -205,27 +205,103 @@ static bool getSystemRegistryString(const char *keyPath, const char *valueName,
#endif // USE_WIN32
}
+// Convert LLVM's ArchType
+// to the corresponding name of Windows SDK libraries subfolder
+static StringRef getWindowsSDKArch(llvm::Triple::ArchType Arch) {
+ switch (Arch) {
+ case llvm::Triple::x86:
+ return "x86";
+ case llvm::Triple::x86_64:
+ return "x64";
+ case llvm::Triple::arm:
+ return "arm";
+ default:
+ return "";
+ }
+}
+
+// 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 getWindows10SDKVersion(const std::string &SDKPath,
+ std::string &SDKVersion) {
+ SDKVersion.clear();
+
+ std::error_code EC;
+ llvm::SmallString<128> IncludePath(SDKPath);
+ llvm::sys::path::append(IncludePath, "Include");
+ for (llvm::sys::fs::directory_iterator DirIt(IncludePath, EC), DirEnd;
+ DirIt != DirEnd && !EC; DirIt.increment(EC)) {
+ if (!llvm::sys::fs::is_directory(DirIt->path()))
+ continue;
+ StringRef CandidateName = llvm::sys::path::filename(DirIt->path());
+ // If WDK is installed, there could be subfolders like "wdf" in the
+ // "Include" directory.
+ // Allow only directories which names start with "10.".
+ if (!CandidateName.startswith("10."))
+ continue;
+ if (CandidateName > SDKVersion)
+ SDKVersion = CandidateName;
+ }
+
+ return !SDKVersion.empty();
+}
+
/// \brief Get Windows SDK installation directory.
-bool MSVCToolChain::getWindowsSDKDir(std::string &path, int &major,
- int &minor) const {
- std::string sdkVersion;
+bool MSVCToolChain::getWindowsSDKDir(std::string &Path, int &Major,
+ std::string &WindowsSDKIncludeVersion,
+ std::string &WindowsSDKLibVersion) const {
+ std::string RegistrySDKVersion;
// Try the Windows registry.
- bool hasSDKDir = getSystemRegistryString(
- "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
- "InstallationFolder", path, &sdkVersion);
- if (!sdkVersion.empty())
- std::sscanf(sdkVersion.c_str(), "v%d.%d", &major, &minor);
- return hasSDKDir && !path.empty();
+ 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 (llvm::sys::fs::exists(TestPath.c_str())) {
+ WindowsSDKLibVersion = Test;
+ break;
+ }
+ }
+ return !WindowsSDKLibVersion.empty();
+ }
+ if (Major == 10) {
+ if (!getWindows10SDKVersion(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(std::string &path) const {
std::string sdkPath;
int sdkMajor = 0;
- int sdkMinor = 0;
+ std::string windowsSDKIncludeVersion;
+ std::string windowsSDKLibVersion;
path.clear();
- if (!getWindowsSDKDir(sdkPath, sdkMajor, sdkMinor))
+ if (!getWindowsSDKDir(sdkPath, sdkMajor, windowsSDKIncludeVersion,
+ windowsSDKLibVersion))
return false;
llvm::SmallString<128> libPath(sdkPath);
@@ -245,44 +321,57 @@ bool MSVCToolChain::getWindowsSDKLibraryPath(std::string &path) const {
return false;
}
} else {
- // 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"};
- bool found = false;
- for (const char *test : tests) {
- llvm::SmallString<128> testPath(libPath);
- llvm::sys::path::append(testPath, test);
- if (llvm::sys::fs::exists(testPath.c_str())) {
- libPath = testPath;
- found = true;
- break;
- }
- }
-
- if (!found)
- return false;
-
- llvm::sys::path::append(libPath, "um");
- switch (getArch()) {
- case llvm::Triple::x86:
- llvm::sys::path::append(libPath, "x86");
- break;
- case llvm::Triple::x86_64:
- llvm::sys::path::append(libPath, "x64");
- break;
- case llvm::Triple::arm:
- llvm::sys::path::append(libPath, "arm");
- break;
- default:
+ const StringRef archName = getWindowsSDKArch(getArch());
+ if (archName.empty())
return false;
- }
+ llvm::sys::path::append(libPath, windowsSDKLibVersion, "um", archName);
}
path = 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 clang::driver::toolchains::MSVCToolChain::useUniversalCRT(
+ std::string &VisualStudioDir) const {
+ llvm::SmallString<128> TestPath(VisualStudioDir);
+ llvm::sys::path::append(TestPath, "VC\\include\\stdlib.h");
+
+ return !llvm::sys::fs::exists(TestPath);
+}
+
+bool MSVCToolChain::getUniversalCRTSdkDir(std::string &Path,
+ std::string &UCRTVersion) const {
+ // 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 getWindows10SDKVersion(Path, UCRTVersion);
+}
+
+bool MSVCToolChain::getUniversalCRTLibraryPath(std::string &Path) const {
+ std::string UniversalCRTSdkPath;
+ std::string UCRTVersion;
+
+ Path.clear();
+ if (!getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion))
+ return false;
+
+ StringRef ArchName = getWindowsSDKArch(getArch());
+ if (ArchName.empty())
+ return false;
+
+ llvm::SmallString<128> LibPath(UniversalCRTSdkPath);
+ llvm::sys::path::append(LibPath, "Lib", UCRTVersion, "ucrt", ArchName);
+
+ Path = LibPath.str();
+ return true;
+}
+
// Get the location to use for Visual Studio binaries. The location priority
// is: %VCINSTALLDIR% > %PATH% > newest copy of Visual Studio installed on
// system (as reported by the registry).
@@ -419,12 +508,12 @@ bool MSVCToolChain::getVisualStudioInstallDir(std::string &path) const {
return false;
}
-void MSVCToolChain::AddSystemIncludeWithSubfolder(const ArgList &DriverArgs,
- ArgStringList &CC1Args,
- const std::string &folder,
- const char *subfolder) const {
+void MSVCToolChain::AddSystemIncludeWithSubfolder(
+ const ArgList &DriverArgs, ArgStringList &CC1Args,
+ const std::string &folder, const Twine &subfolder1, const Twine &subfolder2,
+ const Twine &subfolder3) const {
llvm::SmallString<128> path(folder);
- llvm::sys::path::append(path, subfolder);
+ llvm::sys::path::append(path, subfolder1, subfolder2, subfolder3);
addSystemInclude(DriverArgs, CC1Args, path);
}
@@ -434,9 +523,8 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
return;
if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
- SmallString<128> P(getDriver().ResourceDir);
- llvm::sys::path::append(P, "include");
- addSystemInclude(DriverArgs, CC1Args, P);
+ AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, getDriver().ResourceDir,
+ "include");
}
if (DriverArgs.hasArg(options::OPT_nostdlibinc))
@@ -460,16 +548,33 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
if (getVisualStudioInstallDir(VSDir)) {
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, VSDir, "VC\\include");
+ if (useUniversalCRT(VSDir)) {
+ std::string UniversalCRTSdkPath;
+ std::string UCRTVersion;
+ if (getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion)) {
+ AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath,
+ "Include", UCRTVersion, "ucrt");
+ }
+ }
+
std::string WindowsSDKDir;
- int major, minor;
- if (getWindowsSDKDir(WindowsSDKDir, major, minor)) {
+ int major;
+ std::string windowsSDKIncludeVersion;
+ std::string windowsSDKLibVersion;
+ if (getWindowsSDKDir(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.
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
- "include\\shared");
+ "include", windowsSDKIncludeVersion,
+ "shared");
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
- "include\\um");
+ "include", windowsSDKIncludeVersion,
+ "um");
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
- "include\\winrt");
+ "include", windowsSDKIncludeVersion,
+ "winrt");
} else {
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
"include");
@@ -528,3 +633,112 @@ SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
Res |= SanitizerKind::Address;
return Res;
}
+
+llvm::opt::DerivedArgList *
+MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
+ const char *BoundArch) const {
+ DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
+ const OptTable &Opts = getDriver().getOpts();
+
+ // /Oy and /Oy- only has an effect under X86-32.
+ bool SupportsForcingFramePointer = getArch() == llvm::Triple::x86;
+
+ // The -O[12xd] flag actually expands to several flags. We must desugar the
+ // flags so that options embedded can be negated. For example, the '-O2' flag
+ // enables '-Oy'. Expanding '-O2' into its constituent flags allows us to
+ // correctly handle '-O2 -Oy-' where the trailing '-Oy-' disables a single
+ // aspect of '-O2'.
+ //
+ // Note that this expansion logic only applies to the *last* of '[12xd]'.
+
+ // First step is to search for the character we'd like to expand.
+ const char *ExpandChar = nullptr;
+ for (Arg *A : Args) {
+ if (!A->getOption().matches(options::OPT__SLASH_O))
+ continue;
+ StringRef OptStr = A->getValue();
+ for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
+ const char &OptChar = *(OptStr.data() + I);
+ if (OptChar == '1' || OptChar == '2' || OptChar == 'x' || OptChar == 'd')
+ ExpandChar = OptStr.data() + I;
+ }
+ }
+
+ // The -O flag actually takes an amalgam of other options. For example,
+ // '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'.
+ for (Arg *A : Args) {
+ if (!A->getOption().matches(options::OPT__SLASH_O)) {
+ DAL->append(A);
+ continue;
+ }
+
+ StringRef OptStr = A->getValue();
+ for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
+ const char &OptChar = *(OptStr.data() + I);
+ switch (OptChar) {
+ default:
+ break;
+ case '1':
+ case '2':
+ case 'x':
+ case 'd':
+ if (&OptChar == ExpandChar) {
+ if (OptChar == 'd') {
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_O0));
+ } else {
+ if (OptChar == '1') {
+ DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
+ } else if (OptChar == '2' || OptChar == 'x') {
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
+ DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
+ }
+ if (SupportsForcingFramePointer)
+ DAL->AddFlagArg(A,
+ Opts.getOption(options::OPT_fomit_frame_pointer));
+ if (OptChar == '1' || OptChar == '2')
+ DAL->AddFlagArg(A,
+ Opts.getOption(options::OPT_ffunction_sections));
+ }
+ }
+ break;
+ case 'b':
+ if (I + 1 != E && isdigit(OptStr[I + 1]))
+ ++I;
+ break;
+ case 'g':
+ break;
+ case 'i':
+ if (I + 1 != E && OptStr[I + 1] == '-') {
+ ++I;
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin));
+ } else {
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
+ }
+ break;
+ case 's':
+ DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
+ break;
+ case 't':
+ DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
+ break;
+ case 'y': {
+ bool OmitFramePointer = true;
+ if (I + 1 != E && OptStr[I + 1] == '-') {
+ OmitFramePointer = false;
+ ++I;
+ }
+ if (SupportsForcingFramePointer) {
+ if (OmitFramePointer)
+ DAL->AddFlagArg(A,
+ Opts.getOption(options::OPT_fomit_frame_pointer));
+ else
+ DAL->AddFlagArg(
+ A, Opts.getOption(options::OPT_fno_omit_frame_pointer));
+ }
+ break;
+ }
+ }
+ }
+ }
+ return DAL;
+}
OpenPOWER on IntegriCloud