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