From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: PJ Reiniger Date: Tue, 3 May 2022 20:22:38 -0400 Subject: [PATCH 15/34] Windows support --- .../llvm/Support/Windows/WindowsSupport.h | 56 +++++------ llvm/lib/Support/ConvertUTF.cpp | 95 +++++++++++++++++++ llvm/lib/Support/ErrorHandling.cpp | 14 +-- llvm/lib/Support/raw_ostream.cpp | 1 - 4 files changed, 129 insertions(+), 37 deletions(-) diff --git a/llvm/include/llvm/Support/Windows/WindowsSupport.h b/llvm/include/llvm/Support/Windows/WindowsSupport.h index 30644ef7f62cb81a33f2b62068f77f4e7f3f5019..994a145668d8f7b6c4569099fdb3b1c9096a6b30 100644 --- a/llvm/include/llvm/Support/Windows/WindowsSupport.h +++ b/llvm/include/llvm/Support/Windows/WindowsSupport.h @@ -33,8 +33,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" @@ -42,18 +40,46 @@ #include #include #include +#define WIN32_NO_STATUS #include +#undef WIN32_NO_STATUS +#include +#include // Must be included after windows.h #include 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. -LLVM_ABI bool RunningWindows8OrGreater(); +inline bool RunningWindows8OrGreater() { + // Windows 8 is version 6.2, service pack 0. + return GetWindowsOSVersion() >= llvm::VersionTuple(6, 2, 0, 0); +} /// Determines if the program is running on Windows 11 or Windows Server 2022. LLVM_ABI bool RunningWindows11OrGreater(); @@ -229,30 +255,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. -LLVM_ABI std::error_code -GetCommandLineArguments(SmallVectorImpl &Args, - BumpPtrAllocator &Alloc); - -/// Convert UTF-8 path to a suitable UTF-16 path for use with the Win32 Unicode -/// File API. -LLVM_ABI std::error_code widenPath(const Twine &Path8, - SmallVectorImpl &Path16, - size_t MaxPathLen = MAX_PATH); - -/// Retrieves the handle to a in-memory system module such as ntdll.dll, while -/// ensuring we're not retrieving a malicious injected module but a module -/// loaded from the system path. -LLVM_ABI HMODULE loadSystemModuleSecure(LPCWSTR lpModuleName); - -/// Convert a UTF-8 path to a long form UTF-8 path expanding any short 8.3 form -/// components. -LLVM_ABI std::error_code makeLongFormPath(const Twine &Path8, - llvm::SmallVectorImpl &Result8); -} // end namespace windows } // end namespace sys } // end namespace llvm. diff --git a/llvm/lib/Support/ConvertUTF.cpp b/llvm/lib/Support/ConvertUTF.cpp index 63f92631d5b473cf9a69a06eddf4271304e8c730..f8551c7136ed44b8ed8c2f0bc4498145af504dd0 100644 --- a/llvm/lib/Support/ConvertUTF.cpp +++ b/llvm/lib/Support/ConvertUTF.cpp @@ -67,6 +67,11 @@ #endif #include +#ifdef _WIN32 +#include "wpi/util/WindowsError.hpp" +#include "Windows/WindowsSupport.hpp" +#endif + /* * This code extensively uses fall-through switches. * Keep the compiler from warning about that. @@ -759,6 +764,96 @@ ConversionResult ConvertUTF8toUTF32(const UTF8 **sourceStart, --------------------------------------------------------------------- */ +#ifdef _WIN32 + +namespace sys { +namespace windows { +std::error_code CodePageToUTF16(unsigned codepage, + std::string_view original, + wpi::util::SmallVectorImpl &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::util::SmallVectorImpl &utf16) { + return CodePageToUTF16(CP_UTF8, utf8, utf16); +} + +std::error_code CurCPToUTF16(std::string_view curcp, + wpi::util::SmallVectorImpl &utf16) { + return CodePageToUTF16(CP_ACP, curcp, utf16); +} + +static +std::error_code UTF16ToCodePage(unsigned codepage, const wchar_t *utf16, + size_t utf16_len, + wpi::util::SmallVectorImpl &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::util::SmallVectorImpl &utf8) { + return UTF16ToCodePage(CP_UTF8, utf16, utf16_len, utf8); +} + +std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len, + wpi::util::SmallVectorImpl &curcp) { + return UTF16ToCodePage(CP_ACP, utf16, utf16_len, curcp); +} + +} // end namespace windows +} // end namespace sys + +#endif // _WIN32 + } // namespace llvm ConvertUTF_RESTORE_WARNINGS diff --git a/llvm/lib/Support/ErrorHandling.cpp b/llvm/lib/Support/ErrorHandling.cpp index c4366de2aec2f1730954aecfc627dd0e164481ab..cc0e4665da20b619f0cf52a25b0c71bdf78e62f6 100644 --- a/llvm/lib/Support/ErrorHandling.cpp +++ b/llvm/lib/Support/ErrorHandling.cpp @@ -60,7 +60,11 @@ static std::mutex BadAllocErrorHandlerMutex; static bool write_retry(int fd, const char *buf, size_t count) { while (count > 0) { +#ifdef _WIN32 + int written = sys::RetryAfterSignal(-1, ::_write, fd, buf, count); +#else ssize_t written = sys::RetryAfterSignal(-1, ::write, fd, buf, count); +#endif if (written <= 0) return false; buf += written; @@ -115,15 +119,7 @@ void llvm::report_fatal_error(std::string_view Reason, bool GenCrashDiag) { write_retry(2, MessageStr.data(), MessageStr.size()); } - // If we reached here, we are failing ungracefully. Run the interrupt handlers - // to make sure any special cleanups get done, in particular that we remove - // files registered with RemoveFileOnSignal. - sys::RunInterruptHandlers(); - - if (GenCrashDiag) - abort(); - else - exit(1); + exit(1); } void llvm::reportFatalInternalError(const char *reason) { diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp index 459189b0f0a006d465a857f26a78968c4f234a8d..7a834a0562af1f7da4315e735fe444278a9eef0e 100644 --- a/llvm/lib/Support/raw_ostream.cpp +++ b/llvm/lib/Support/raw_ostream.cpp @@ -519,7 +519,6 @@ void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) { DWORD WinLastError = GetLastError(); if (WinLastError == ERROR_BROKEN_PIPE || (WinLastError == ERROR_NO_DATA && errno == EINVAL)) { - llvm::sys::CallOneShotPipeSignalHandler(); errno = EPIPE; } #endif