blob: 07d973b94782bc9e3682a4629a2944f028ac0368 [file] [log] [blame]
James Kuszmaulcf324122023-01-14 14:07:17 -08001From 36f7f08e257f2b58b2894f165a38ff2a831aed8f Mon Sep 17 00:00:00 2001
2From: PJ Reiniger <pj.reiniger@gmail.com>
3Date: Tue, 3 May 2022 20:22:38 -0400
4Subject: [PATCH 19/28] Windows support
5
6---
7 .../llvm/Support/Windows/WindowsSupport.h | 45 +++++----
8 llvm/lib/Support/ConvertUTF.cpp | 95 +++++++++++++++++++
9 2 files changed, 124 insertions(+), 16 deletions(-)
10
11diff --git a/llvm/include/llvm/Support/Windows/WindowsSupport.h b/llvm/include/llvm/Support/Windows/WindowsSupport.h
12index 180803fbd..31120cfa0 100644
13--- a/llvm/include/llvm/Support/Windows/WindowsSupport.h
14+++ b/llvm/include/llvm/Support/Windows/WindowsSupport.h
15@@ -35,8 +35,6 @@
16
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/ADT/StringExtras.h"
19-#include "llvm/Config/llvm-config.h" // Get build system configuration settings
20-#include "llvm/Support/Allocator.h"
21 #include "llvm/Support/Chrono.h"
22 #include "llvm/Support/Compiler.h"
23 #include "llvm/Support/ErrorHandling.h"
24@@ -44,18 +42,46 @@
25 #include <cassert>
26 #include <string>
27 #include <system_error>
28+#define WIN32_NO_STATUS
29 #include <windows.h>
30+#undef WIN32_NO_STATUS
31+#include <winternl.h>
32+#include <ntstatus.h>
33
34 // Must be included after windows.h
35 #include <wincrypt.h>
36
37 namespace llvm {
38
39+/// Returns the Windows version as Major.Minor.0.BuildNumber. Uses
40+/// RtlGetVersion or GetVersionEx under the hood depending on what is available.
41+/// GetVersionEx is deprecated, but this API exposes the build number which can
42+/// be useful for working around certain kernel bugs.
43+inline llvm::VersionTuple GetWindowsOSVersion() {
44+ typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
45+ HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
46+ if (hMod) {
47+ auto getVer = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion");
48+ if (getVer) {
49+ RTL_OSVERSIONINFOEXW info{};
50+ info.dwOSVersionInfoSize = sizeof(info);
51+ if (getVer((PRTL_OSVERSIONINFOW)&info) == ((NTSTATUS)0x00000000L)) {
52+ return llvm::VersionTuple(info.dwMajorVersion, info.dwMinorVersion, 0,
53+ info.dwBuildNumber);
54+ }
55+ }
56+ }
57+ return llvm::VersionTuple(0, 0, 0, 0);
58+}
59+
60 /// Determines if the program is running on Windows 8 or newer. This
61 /// reimplements one of the helpers in the Windows 8.1 SDK, which are intended
62 /// to supercede raw calls to GetVersionEx. Old SDKs, Cygwin, and MinGW don't
63 /// yet have VersionHelpers.h, so we have our own helper.
64-bool RunningWindows8OrGreater();
65+inline bool RunningWindows8OrGreater() {
66+ // Windows 8 is version 6.2, service pack 0.
67+ return GetWindowsOSVersion() >= llvm::VersionTuple(6, 2, 0, 0);
68+}
69
70 /// Returns the Windows version as Major.Minor.0.BuildNumber. Uses
71 /// RtlGetVersion or GetVersionEx under the hood depending on what is available.
72@@ -228,19 +254,6 @@ inline FILETIME toFILETIME(TimePoint<> TP) {
73 return Time;
74 }
75
76-namespace windows {
77-// Returns command line arguments. Unlike arguments given to main(),
78-// this function guarantees that the returned arguments are encoded in
79-// UTF-8 regardless of the current code page setting.
80-std::error_code GetCommandLineArguments(SmallVectorImpl<const char *> &Args,
81- BumpPtrAllocator &Alloc);
82-
83-/// Convert UTF-8 path to a suitable UTF-16 path for use with the Win32 Unicode
84-/// File API.
85-std::error_code widenPath(const Twine &Path8, SmallVectorImpl<wchar_t> &Path16,
86- size_t MaxPathLen = MAX_PATH);
87-
88-} // end namespace windows
89 } // end namespace sys
90 } // end namespace llvm.
91
92diff --git a/llvm/lib/Support/ConvertUTF.cpp b/llvm/lib/Support/ConvertUTF.cpp
93index e24a918c5..c906ded91 100644
94--- a/llvm/lib/Support/ConvertUTF.cpp
95+++ b/llvm/lib/Support/ConvertUTF.cpp
96@@ -51,6 +51,11 @@
97 #endif
98 #include <assert.h>
99
100+#ifdef _WIN32
101+#include "wpi/WindowsError.h"
102+#include "Windows/WindowsSupport.h"
103+#endif
104+
105 /*
106 * This code extensively uses fall-through switches.
107 * Keep the compiler from warning about that.
108@@ -733,6 +738,96 @@ ConversionResult ConvertUTF8toUTF32(const UTF8 **sourceStart,
109
110 --------------------------------------------------------------------- */
111
112+#ifdef _WIN32
113+
114+namespace sys {
115+namespace windows {
116+std::error_code CodePageToUTF16(unsigned codepage,
117+ std::string_view original,
118+ wpi::SmallVectorImpl<wchar_t> &utf16) {
119+ if (!original.empty()) {
120+ int len = ::MultiByteToWideChar(codepage, MB_ERR_INVALID_CHARS, original.data(),
121+ original.size(), utf16.begin(), 0);
122+
123+ if (len == 0) {
124+ return mapWindowsError(::GetLastError());
125+ }
126+
127+ utf16.reserve(len + 1);
128+ utf16.resize_for_overwrite(len);
129+
130+ len = ::MultiByteToWideChar(codepage, MB_ERR_INVALID_CHARS, original.data(),
131+ original.size(), utf16.begin(), utf16.size());
132+
133+ if (len == 0) {
134+ return mapWindowsError(::GetLastError());
135+ }
136+ }
137+
138+ // Make utf16 null terminated.
139+ utf16.push_back(0);
140+ utf16.pop_back();
141+
142+ return std::error_code();
143+}
144+
145+std::error_code UTF8ToUTF16(std::string_view utf8,
146+ wpi::SmallVectorImpl<wchar_t> &utf16) {
147+ return CodePageToUTF16(CP_UTF8, utf8, utf16);
148+}
149+
150+std::error_code CurCPToUTF16(std::string_view curcp,
151+ wpi::SmallVectorImpl<wchar_t> &utf16) {
152+ return CodePageToUTF16(CP_ACP, curcp, utf16);
153+}
154+
155+static
156+std::error_code UTF16ToCodePage(unsigned codepage, const wchar_t *utf16,
157+ size_t utf16_len,
158+ wpi::SmallVectorImpl<char> &converted) {
159+ if (utf16_len) {
160+ // Get length.
161+ int len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, converted.begin(),
162+ 0, NULL, NULL);
163+
164+ if (len == 0) {
165+ return mapWindowsError(::GetLastError());
166+ }
167+
168+ converted.reserve(len);
169+ converted.resize_for_overwrite(len);
170+
171+ // Now do the actual conversion.
172+ len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, converted.data(),
173+ converted.size(), NULL, NULL);
174+
175+ if (len == 0) {
176+ return mapWindowsError(::GetLastError());
177+ }
178+ }
179+
180+ // Make the new string null terminated.
181+ converted.push_back(0);
182+ converted.pop_back();
183+
184+ return std::error_code();
185+}
186+
187+std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len,
188+ wpi::SmallVectorImpl<char> &utf8) {
189+ return UTF16ToCodePage(CP_UTF8, utf16, utf16_len, utf8);
190+}
191+
192+std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len,
193+ wpi::SmallVectorImpl<char> &curcp) {
194+ return UTF16ToCodePage(CP_ACP, utf16, utf16_len, curcp);
195+}
196+
197+} // end namespace windows
198+} // end namespace sys
199+
200+#endif // _WIN32
201+
202 } // namespace llvm
203
204 ConvertUTF_RESTORE_WARNINGS