Skip to content

Commit ded0801

Browse files
authored
[libc] Add osutils for Windows and make libc and its tests build on Windows target (#104676)
This PR first adds osutils for Windows, and changes some libc code to make libc and its tests build on the Windows target. It then temporarily disables some libc tests that are currently problematic on Windows. Specifically, the changes besides the addition of osutils include: - Macro `LIBC_TYPES_HAS_FLOAT16` is disabled on Windows. `clang-cl` generates calls to functions in `compiler-rt` to handle float16 arithmetic and these functions are currently not linked in on Windows. - Macro `LIBC_TYPES_HAS_INT128` is disabled on Windows. - The invocation to `::aligned_malloc` is changed to an invocation to `::_aligned_malloc`. - The following unit tests are temporarily disabled because they currently fail on Windows: - `test.src.__support.big_int_test` - `test.src.__support.arg_list_test` - `test.src.fenv.getenv_and_setenv_test` - Tests involving `__m128i`, `__m256i`, and `__m512i` in `test.src.string.memory_utils.op_tests.cpp` - `test_range_errors` in `libc/test/src/math/smoke/AddTest.h` and `libc/test/src/math/smoke/SubTest.h`
1 parent 9469836 commit ded0801

File tree

23 files changed

+163
-13
lines changed

23 files changed

+163
-13
lines changed

libc/cmake/modules/LLVMLibCArchitectures.cmake

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,13 @@ if(explicit_target_triple AND
206206
endif()
207207
endif()
208208

209+
210+
# Windows does not support full mode build.
211+
if (LIBC_TARGET_OS_IS_WINDOWS AND LLVM_LIBC_FULL_BUILD)
212+
message(FATAL_ERROR "Windows does not support full mode build.")
213+
endif ()
214+
215+
209216
message(STATUS
210217
"Building libc for ${LIBC_TARGET_ARCHITECTURE} on ${LIBC_TARGET_OS} with
211218
LIBC_COMPILE_OPTIONS_DEFAULT: ${LIBC_COMPILE_OPTIONS_DEFAULT}")

libc/include/llvm-libc-macros/float16-macros.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313

1414
#if defined(__FLT16_MANT_DIG__) && \
1515
(!defined(__GNUC__) || __GNUC__ >= 13 || defined(__clang__)) && \
16-
!defined(__arm__) && !defined(_M_ARM) && !defined(__riscv)
16+
!defined(__arm__) && !defined(_M_ARM) && !defined(__riscv) && \
17+
!defined(_WIN32)
1718
#define LIBC_TYPES_HAS_FLOAT16
1819

1920
// TODO: This would no longer be required if HdrGen let us guard function

libc/include/llvm-libc-macros/stdckdint-macros.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
#define LLVM_LIBC_MACROS_STDCKDINT_MACROS_H
1111

1212
// We need to use __builtin_*_overflow from GCC/Clang to implement the overflow
13-
// macros. Check __GNUC__ for availability of such builtins.
14-
#ifdef __GNUC__
13+
// macros. Check __GNUC__ or __clang__ for availability of such builtins.
14+
// Note that clang-cl defines __clang__ only and does not define __GNUC__ so we
15+
// have to check for both.
16+
#if defined(__GNUC__) || defined(__clang__)
1517
// clang/gcc overlay may provides similar macros, we need to avoid redefining
1618
// them.
1719
#ifndef __STDC_VERSION_STDCKDINT_H__

libc/src/__support/CPP/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,4 +199,5 @@ add_object_library(
199199
DEPENDS
200200
libc.include.stdlib
201201
libc.src.__support.common
202+
libc.src.__support.macros.properties.os
202203
)

libc/src/__support/CPP/new.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,29 @@ void operator delete(void *mem, std::align_val_t) noexcept { ::free(mem); }
1616
void operator delete(void *mem, size_t) noexcept { ::free(mem); }
1717

1818
void operator delete(void *mem, size_t, std::align_val_t) noexcept {
19+
#ifdef LIBC_TARGET_OS_IS_WINDOWS
20+
::_aligned_free(mem);
21+
#else
1922
::free(mem);
23+
#endif
2024
}
2125

2226
void operator delete[](void *mem) noexcept { ::free(mem); }
2327

24-
void operator delete[](void *mem, std::align_val_t) noexcept { ::free(mem); }
28+
void operator delete[](void *mem, std::align_val_t) noexcept {
29+
#ifdef LIBC_TARGET_OS_IS_WINDOWS
30+
::_aligned_free(mem);
31+
#else
32+
::free(mem);
33+
#endif
34+
}
2535

2636
void operator delete[](void *mem, size_t) noexcept { ::free(mem); }
2737

2838
void operator delete[](void *mem, size_t, std::align_val_t) noexcept {
39+
#ifdef LIBC_TARGET_OS_IS_WINDOWS
40+
::_aligned_free(mem);
41+
#else
2942
::free(mem);
43+
#endif
3044
}

libc/src/__support/CPP/new.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include "src/__support/common.h"
1313
#include "src/__support/macros/config.h"
14+
#include "src/__support/macros/properties/os.h"
1415

1516
#include <stddef.h> // For size_t
1617
#include <stdlib.h> // For malloc, free etc.
@@ -47,7 +48,15 @@ class AllocChecker {
4748

4849
LIBC_INLINE static void *aligned_alloc(size_t s, std::align_val_t align,
4950
AllocChecker &ac) {
51+
#ifdef LIBC_TARGET_OS_IS_WINDOWS
52+
// std::aligned_alloc is not available on Windows because std::free on
53+
// Windows cannot deallocate any over-aligned memory. Microsoft provides an
54+
// alternative for std::aligned_alloc named _aligned_malloc, but it must be
55+
// paired with _aligned_free instead of std::free.
56+
void *mem = ::_aligned_malloc(static_cast<size_t>(align), s);
57+
#else
5058
void *mem = ::aligned_alloc(static_cast<size_t>(align), s);
59+
#endif
5160
ac = (mem != nullptr);
5261
return mem;
5362
}

libc/src/__support/OSUtil/io.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include "linux/io.h"
2020
#elif defined(__Fuchsia__)
2121
#include "fuchsia/io.h"
22+
#elif defined(_WIN32)
23+
#include "windows/io.h"
2224
#elif defined(__ELF__)
2325
// TODO: Ideally we would have LIBC_TARGET_OS_IS_BAREMETAL.
2426
#include "baremetal/io.h"
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
add_object_library(
2+
windows_util
3+
SRCS
4+
exit.cpp
5+
io.cpp
6+
HDRS
7+
io.h
8+
DEPENDS
9+
libc.src.__support.macros.config
10+
)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//===-- Windows implementation of an exit function ------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/__support/macros/config.h"
10+
11+
// On Windows we cannot make direct syscalls since Microsoft changes system call
12+
// IDs periodically. We must rely on functions exported from ntdll.dll or
13+
// kernel32.dll to invoke system service procedures.
14+
#define WIN32_LEAN_AND_MEAN
15+
#include <Windows.h>
16+
17+
namespace LIBC_NAMESPACE_DECL {
18+
namespace internal {
19+
20+
[[noreturn]] void exit(int status) { ::ExitProcess(status); }
21+
22+
} // namespace internal
23+
} // namespace LIBC_NAMESPACE_DECL
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//===------------- Windows implementation of IO utils -----------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "io.h"
10+
#include "src/__support/macros/config.h"
11+
12+
// On Windows we cannot make direct syscalls since Microsoft changes system call
13+
// IDs periodically. We must rely on functions exported from ntdll.dll or
14+
// kernel32.dll to invoke system service procedures.
15+
#define WIN32_LEAN_AND_MEAN
16+
#include <Windows.h>
17+
18+
namespace LIBC_NAMESPACE_DECL {
19+
20+
void write_to_stderr(cpp::string_view msg) {
21+
::HANDLE stream = ::GetStdHandle(STD_ERROR_HANDLE);
22+
::WriteFile(stream, msg.data(), msg.size(), nullptr, nullptr);
23+
}
24+
25+
} // namespace LIBC_NAMESPACE_DECL

0 commit comments

Comments
 (0)