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
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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+
#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_WINDOWS_IO_H
10+
#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_WINDOWS_IO_H
11+
12+
#include "src/__support/CPP/string_view.h"
13+
#include "src/__support/macros/config.h"
14+
15+
namespace LIBC_NAMESPACE_DECL {
16+
17+
void write_to_stderr(cpp::string_view msg);
18+
19+
} // namespace LIBC_NAMESPACE_DECL
20+
21+
#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_WINDOWS_IO_H

libc/src/__support/macros/properties/types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
#endif // UINT64_MAX
3636

3737
// int128 / uint128 support
38-
#if defined(__SIZEOF_INT128__)
38+
#if defined(__SIZEOF_INT128__) && !defined(LIBC_TARGET_OS_IS_WINDOWS)
3939
#define LIBC_TYPES_HAS_INT128
4040
#endif // defined(__SIZEOF_INT128__)
4141

libc/test/src/__support/CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,14 @@ add_libc_test(
140140
arg_list_test.cpp
141141
DEPENDS
142142
libc.src.__support.arg_list
143+
libc.src.__support.macros.properties.os
143144
)
144145

145-
if(NOT LIBC_TARGET_ARCHITECTURE_IS_NVPTX)
146+
# TODO: clang-cl generates calls into runtime library functions to
147+
# handle 128-bit integer arithmetics and conversions which are not yet
148+
# available on Windows. Re-enable 128-bit integer support on Windows once
149+
# these functions are ready.
150+
if(NOT LIBC_TARGET_ARCHITECTURE_IS_NVPTX AND NOT LIBC_TARGET_OS_IS_WINDOWS)
146151
add_libc_test(
147152
big_int_test
148153
SUITE

libc/test/src/__support/FPUtil/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ add_libc_test(
2525
libc.src.__support.FPUtil.fp_bits
2626
libc.src.__support.FPUtil.fpbits_str
2727
libc.src.__support.integer_literals
28+
libc.src.__support.macros.properties.types
2829
libc.src.__support.sign
2930
)
3031

libc/test/src/__support/FPUtil/fpbits_test.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "src/__support/FPUtil/FPBits.h"
1010
#include "src/__support/FPUtil/fpbits_str.h"
1111
#include "src/__support/integer_literals.h"
12+
#include "src/__support/macros/properties/types.h"
1213
#include "src/__support/sign.h" // Sign
1314
#include "test/UnitTest/Test.h"
1415

@@ -425,13 +426,10 @@ TEST(LlvmLibcFPBitsTest, DoubleType) {
425426
EXPECT_EQ(quiet_nan.is_quiet_nan(), true);
426427
}
427428

428-
#ifdef LIBC_TARGET_ARCH_IS_X86
429+
#ifdef LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
429430
TEST(LlvmLibcFPBitsTest, X86LongDoubleType) {
430431
using LongDoubleBits = FPBits<long double>;
431432

432-
if constexpr (sizeof(long double) == sizeof(double))
433-
return; // The tests for the "double" type cover for this case.
434-
435433
EXPECT_STREQ(LIBC_NAMESPACE::str(LongDoubleBits::inf(Sign::POS)).c_str(),
436434
"(+Infinity)");
437435
EXPECT_STREQ(LIBC_NAMESPACE::str(LongDoubleBits::inf(Sign::NEG)).c_str(),

libc/test/src/__support/arg_list_test.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "src/__support/arg_list.h"
10+
#include "src/__support/macros/properties/os.h"
1011

1112
#include "test/UnitTest/Test.h"
1213

@@ -120,7 +121,7 @@ TEST(LlvmLibcArgListTest, TestStructTypes) {
120121
}
121122

122123
// Test vector extensions from clang.
123-
#if __has_attribute(ext_vector_type)
124+
#if !defined(LIBC_TARGET_OS_IS_WINDOWS) && __has_attribute(ext_vector_type)
124125

125126
using int1 = int __attribute__((ext_vector_type(1)));
126127
using int2 = int __attribute__((ext_vector_type(2)));

libc/test/src/fenv/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ add_libc_unittest(
4141
libc.src.fenv.fesetenv
4242
libc.src.fenv.fesetround
4343
libc.src.__support.FPUtil.fenv_impl
44+
libc.src.__support.macros.properties.os
4445
LINK_LIBRARIES
4546
LibcFPTestHelpers
4647
)

libc/test/src/fenv/getenv_and_setenv_test.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@
1313
#include "src/fenv/fesetround.h"
1414

1515
#include "src/__support/FPUtil/FEnvImpl.h"
16+
#include "src/__support/macros/properties/os.h"
1617
#include "test/UnitTest/FEnvSafeTest.h"
1718
#include "test/UnitTest/Test.h"
1819

1920
#include "excepts.h"
2021

2122
using LlvmLibcFEnvTest = LIBC_NAMESPACE::testing::FEnvSafeTest;
2223

24+
#ifndef LIBC_TARGET_OS_IS_WINDOWS
2325
TEST_F(LlvmLibcFEnvTest, GetEnvAndSetEnv) {
2426
// We will disable all exceptions to prevent invocation of the exception
2527
// handler.
@@ -71,8 +73,9 @@ TEST_F(LlvmLibcFEnvTest, Set_FE_DFL_ENV) {
7173
int rm = LIBC_NAMESPACE::fegetround();
7274
EXPECT_EQ(rm, FE_TONEAREST);
7375
}
76+
#endif
7477

75-
#ifdef _WIN32
78+
#ifdef LIBC_TARGET_OS_IS_WINDOWS
7679
TEST_F(LlvmLibcFEnvTest, Windows_Set_Get_Test) {
7780
// If a valid fenv_t is written, then reading it back out should be identical.
7881
fenv_t setEnv = {0x7e00053e, 0x0f00000f};

libc/test/src/math/smoke/AddTest.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "hdr/errno_macros.h"
1313
#include "hdr/fenv_macros.h"
1414
#include "src/__support/FPUtil/BasicOperations.h"
15+
#include "src/__support/macros/properties/os.h"
1516
#include "test/UnitTest/FEnvSafeTest.h"
1617
#include "test/UnitTest/FPMatcher.h"
1718
#include "test/UnitTest/Test.h"
@@ -53,6 +54,7 @@ class AddTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
5354
}
5455

5556
void test_range_errors(AddFunc func) {
57+
#ifndef LIBC_TARGET_OS_IS_WINDOWS
5658
using namespace LIBC_NAMESPACE::fputil::testing;
5759

5860
if (ForceRoundingMode r(RoundingMode::Nearest); r.success) {
@@ -121,6 +123,7 @@ class AddTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
121123
FE_UNDERFLOW | FE_INEXACT);
122124
EXPECT_MATH_ERRNO(ERANGE);
123125
}
126+
#endif
124127
}
125128

126129
void test_inexact_results(AddFunc func) {

0 commit comments

Comments
 (0)