blob: 07d973b94782bc9e3682a4629a2944f028ac0368 [file] [log] [blame]
From 36f7f08e257f2b58b2894f165a38ff2a831aed8f Mon Sep 17 00:00:00 2001
From: PJ Reiniger <pj.reiniger@gmail.com>
Date: Tue, 3 May 2022 20:22:38 -0400
Subject: [PATCH 19/28] Windows support
---
.../llvm/Support/Windows/WindowsSupport.h | 45 +++++----
llvm/lib/Support/ConvertUTF.cpp | 95 +++++++++++++++++++
2 files changed, 124 insertions(+), 16 deletions(-)
diff --git a/llvm/include/llvm/Support/Windows/WindowsSupport.h b/llvm/include/llvm/Support/Windows/WindowsSupport.h
index 180803fbd..31120cfa0 100644
--- a/llvm/include/llvm/Support/Windows/WindowsSupport.h
+++ b/llvm/include/llvm/Support/Windows/WindowsSupport.h
@@ -35,8 +35,6 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/Config/llvm-config.h" // Get build system configuration settings
-#include "llvm/Support/Allocator.h"
#include "llvm/Support/Chrono.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
@@ -44,18 +42,46 @@
#include <cassert>
#include <string>
#include <system_error>
+#define WIN32_NO_STATUS
#include <windows.h>
+#undef WIN32_NO_STATUS
+#include <winternl.h>
+#include <ntstatus.h>
// Must be included after windows.h
#include <wincrypt.h>
namespace llvm {
+/// Returns the Windows version as Major.Minor.0.BuildNumber. Uses
+/// RtlGetVersion or GetVersionEx under the hood depending on what is available.
+/// GetVersionEx is deprecated, but this API exposes the build number which can
+/// be useful for working around certain kernel bugs.
+inline llvm::VersionTuple GetWindowsOSVersion() {
+ typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
+ HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
+ if (hMod) {
+ auto getVer = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion");
+ if (getVer) {
+ RTL_OSVERSIONINFOEXW info{};
+ info.dwOSVersionInfoSize = sizeof(info);
+ if (getVer((PRTL_OSVERSIONINFOW)&info) == ((NTSTATUS)0x00000000L)) {
+ return llvm::VersionTuple(info.dwMajorVersion, info.dwMinorVersion, 0,
+ info.dwBuildNumber);
+ }
+ }
+ }
+ return llvm::VersionTuple(0, 0, 0, 0);
+}
+
/// Determines if the program is running on Windows 8 or newer. This
/// reimplements one of the helpers in the Windows 8.1 SDK, which are intended
/// to supercede raw calls to GetVersionEx. Old SDKs, Cygwin, and MinGW don't
/// yet have VersionHelpers.h, so we have our own helper.
-bool RunningWindows8OrGreater();
+inline bool RunningWindows8OrGreater() {
+ // Windows 8 is version 6.2, service pack 0.
+ return GetWindowsOSVersion() >= llvm::VersionTuple(6, 2, 0, 0);
+}
/// Returns the Windows version as Major.Minor.0.BuildNumber. Uses
/// RtlGetVersion or GetVersionEx under the hood depending on what is available.
@@ -228,19 +254,6 @@ inline FILETIME toFILETIME(TimePoint<> TP) {
return Time;
}
-namespace windows {
-// Returns command line arguments. Unlike arguments given to main(),
-// this function guarantees that the returned arguments are encoded in
-// UTF-8 regardless of the current code page setting.
-std::error_code GetCommandLineArguments(SmallVectorImpl<const char *> &Args,
- BumpPtrAllocator &Alloc);
-
-/// Convert UTF-8 path to a suitable UTF-16 path for use with the Win32 Unicode
-/// File API.
-std::error_code widenPath(const Twine &Path8, SmallVectorImpl<wchar_t> &Path16,
- size_t MaxPathLen = MAX_PATH);
-
-} // end namespace windows
} // end namespace sys
} // end namespace llvm.
diff --git a/llvm/lib/Support/ConvertUTF.cpp b/llvm/lib/Support/ConvertUTF.cpp
index e24a918c5..c906ded91 100644
--- a/llvm/lib/Support/ConvertUTF.cpp
+++ b/llvm/lib/Support/ConvertUTF.cpp
@@ -51,6 +51,11 @@
#endif
#include <assert.h>
+#ifdef _WIN32
+#include "wpi/WindowsError.h"
+#include "Windows/WindowsSupport.h"
+#endif
+
/*
* This code extensively uses fall-through switches.
* Keep the compiler from warning about that.
@@ -733,6 +738,96 @@ ConversionResult ConvertUTF8toUTF32(const UTF8 **sourceStart,
--------------------------------------------------------------------- */
+#ifdef _WIN32
+
+namespace sys {
+namespace windows {
+std::error_code CodePageToUTF16(unsigned codepage,
+ std::string_view original,
+ wpi::SmallVectorImpl<wchar_t> &utf16) {
+ if (!original.empty()) {
+ int len = ::MultiByteToWideChar(codepage, MB_ERR_INVALID_CHARS, original.data(),
+ original.size(), utf16.begin(), 0);
+
+ if (len == 0) {
+ return mapWindowsError(::GetLastError());
+ }
+
+ utf16.reserve(len + 1);
+ utf16.resize_for_overwrite(len);
+
+ len = ::MultiByteToWideChar(codepage, MB_ERR_INVALID_CHARS, original.data(),
+ original.size(), utf16.begin(), utf16.size());
+
+ if (len == 0) {
+ return mapWindowsError(::GetLastError());
+ }
+ }
+
+ // Make utf16 null terminated.
+ utf16.push_back(0);
+ utf16.pop_back();
+
+ return std::error_code();
+}
+
+std::error_code UTF8ToUTF16(std::string_view utf8,
+ wpi::SmallVectorImpl<wchar_t> &utf16) {
+ return CodePageToUTF16(CP_UTF8, utf8, utf16);
+}
+
+std::error_code CurCPToUTF16(std::string_view curcp,
+ wpi::SmallVectorImpl<wchar_t> &utf16) {
+ return CodePageToUTF16(CP_ACP, curcp, utf16);
+}
+
+static
+std::error_code UTF16ToCodePage(unsigned codepage, const wchar_t *utf16,
+ size_t utf16_len,
+ wpi::SmallVectorImpl<char> &converted) {
+ if (utf16_len) {
+ // Get length.
+ int len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, converted.begin(),
+ 0, NULL, NULL);
+
+ if (len == 0) {
+ return mapWindowsError(::GetLastError());
+ }
+
+ converted.reserve(len);
+ converted.resize_for_overwrite(len);
+
+ // Now do the actual conversion.
+ len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, converted.data(),
+ converted.size(), NULL, NULL);
+
+ if (len == 0) {
+ return mapWindowsError(::GetLastError());
+ }
+ }
+
+ // Make the new string null terminated.
+ converted.push_back(0);
+ converted.pop_back();
+
+ return std::error_code();
+}
+
+std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len,
+ wpi::SmallVectorImpl<char> &utf8) {
+ return UTF16ToCodePage(CP_UTF8, utf16, utf16_len, utf8);
+}
+
+std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len,
+ wpi::SmallVectorImpl<char> &curcp) {
+ return UTF16ToCodePage(CP_ACP, utf16, utf16_len, curcp);
+}
+
+} // end namespace windows
+} // end namespace sys
+
+#endif // _WIN32
+
} // namespace llvm
ConvertUTF_RESTORE_WARNINGS