diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -318,6 +318,10 @@ if(LLVM_LIBC_FULL_BUILD) list(APPEND TARGET_LIBC_ENTRYPOINTS + # network.h entrypoints + libc.src.network.htonl + libc.src.network.htons + # pthread.h entrypoints libc.src.pthread.pthread_atfork libc.src.pthread.pthread_attr_destroy diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -331,6 +331,10 @@ libc.src.dirent.opendir libc.src.dirent.readdir + # network.h entrypoints + libc.src.network.htonl + libc.src.network.htons + # pthread.h entrypoints libc.src.pthread.pthread_atfork libc.src.pthread.pthread_attr_destroy diff --git a/libc/config/linux/x86_64/headers.txt b/libc/config/linux/x86_64/headers.txt --- a/libc/config/linux/x86_64/headers.txt +++ b/libc/config/linux/x86_64/headers.txt @@ -20,6 +20,8 @@ libc.include.time libc.include.unistd + libc.include.arpa_inet + libc.include.sys_auxv libc.include.sys_ioctl libc.include.sys_mman diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt --- a/libc/include/CMakeLists.txt +++ b/libc/include/CMakeLists.txt @@ -68,6 +68,17 @@ .llvm-libc-types.float_t ) +# TODO: This should be conditional on POSIX networking being included. +file(MAKE_DIRECTORY "arpa") + +add_gen_header( + arpa_inet + DEF_FILE arpa/inet.h.def + GEN_HDR arpa/inet.h + DEPENDS + .llvm_libc_common_h +) + add_gen_header( assert DEF_FILE assert.h.def diff --git a/libc/include/arpa/inet.h.def b/libc/include/arpa/inet.h.def new file mode 100644 --- /dev/null +++ b/libc/include/arpa/inet.h.def @@ -0,0 +1,18 @@ +//===-- C standard library header network.h -------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_ARPA_INET_H +#define LLVM_LIBC_ARPA_INET_H + +#include <__llvm-libc-common.h> + +#include + +%%public_api() + +#endif // LLVM_LIBC_ARPA_INET_H diff --git a/libc/spec/posix.td b/libc/spec/posix.td --- a/libc/spec/posix.td +++ b/libc/spec/posix.td @@ -798,6 +798,25 @@ ] >; + HeaderSpec ArpaInet = HeaderSpec< + "arpa/inet.h", + [], // Macros + [], // Types + [], // Enumerations + [ + FunctionSpec< + "htonl", + RetValSpec, + [ArgSpec] + >, + FunctionSpec< + "htons", + RetValSpec, + [ArgSpec] + >, + ] + >; + HeaderSpec PThread = HeaderSpec< "pthread.h", [], // Macros @@ -1260,6 +1279,7 @@ >; let Headers = [ + ArpaInet, CType, Dirent, Errno, diff --git a/libc/spec/spec.td b/libc/spec/spec.td --- a/libc/spec/spec.td +++ b/libc/spec/spec.td @@ -64,6 +64,9 @@ def IntMaxTType : NamedType<"intmax_t">; def UIntMaxTType : NamedType<"uintmax_t">; +def UInt16Type : NamedType<"uint16_t">; +def UInt32Type : NamedType<"uint32_t">; + def OffTType : NamedType<"off_t">; def OffTPtr : PtrType; def SSizeTType : NamedType<"ssize_t">; diff --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt --- a/libc/src/CMakeLists.txt +++ b/libc/src/CMakeLists.txt @@ -24,6 +24,7 @@ endif() add_subdirectory(assert) +add_subdirectory(network) add_subdirectory(setjmp) add_subdirectory(signal) add_subdirectory(spawn) diff --git a/libc/src/network/CMakeLists.txt b/libc/src/network/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/libc/src/network/CMakeLists.txt @@ -0,0 +1,21 @@ +add_entrypoint_object( + htonl + SRCS + htonl.cpp + HDRS + htonl.h + DEPENDS + libc.include.arpa_inet + libc.src.__support.common +) + +add_entrypoint_object( + htons + SRCS + htons.cpp + HDRS + htons.h + DEPENDS + libc.include.arpa_inet + libc.src.__support.common +) diff --git a/libc/src/network/htonl.h b/libc/src/network/htonl.h new file mode 100644 --- /dev/null +++ b/libc/src/network/htonl.h @@ -0,0 +1,20 @@ +//===-- Implementation header of htonl --------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_NETWORK_HTONL_H +#define LLVM_LIBC_SRC_NETWORK_HTONL_H + +#include + +namespace __llvm_libc { + +uint32_t htonl(uint32_t hostlong); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_NETWORK_HTONL_H diff --git a/libc/src/network/htonl.cpp b/libc/src/network/htonl.cpp new file mode 100644 --- /dev/null +++ b/libc/src/network/htonl.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of htonl function ----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/network/htonl.h" +#include "src/__support/common.h" +#include "src/__support/endian.h" + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(uint32_t, htonl, (uint32_t hostlong)) { + return Endian::to_big_endian(hostlong); +} + +} // namespace __llvm_libc diff --git a/libc/src/network/htons.h b/libc/src/network/htons.h new file mode 100644 --- /dev/null +++ b/libc/src/network/htons.h @@ -0,0 +1,20 @@ +//===-- Implementation header of htons --------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_NETWORK_HTONS_H +#define LLVM_LIBC_SRC_NETWORK_HTONS_H + +#include + +namespace __llvm_libc { + +uint16_t htons(uint16_t hostlong); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_NETWORK_HTONS_H diff --git a/libc/src/network/htons.cpp b/libc/src/network/htons.cpp new file mode 100644 --- /dev/null +++ b/libc/src/network/htons.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of htons function ----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/network/htons.h" +#include "src/__support/common.h" +#include "src/__support/endian.h" + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(uint16_t, htons, (uint16_t hostshort)) { + return Endian::to_big_endian(hostshort); +} + +} // namespace __llvm_libc diff --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt --- a/libc/test/src/CMakeLists.txt +++ b/libc/test/src/CMakeLists.txt @@ -50,6 +50,7 @@ add_subdirectory(dirent) add_subdirectory(assert) +add_subdirectory(network) add_subdirectory(setjmp) add_subdirectory(signal) add_subdirectory(spawn) diff --git a/libc/test/src/network/CMakeLists.txt b/libc/test/src/network/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/libc/test/src/network/CMakeLists.txt @@ -0,0 +1,25 @@ +add_libc_testsuite(libc_network_unittests) + +add_libc_unittest( + htonl + SUITE + libc_network_unittests + SRCS + htonl_test.cpp + CXX_STANDARD + 20 + DEPENDS + libc.src.network.htonl +) + +add_libc_unittest( + htons + SUITE + libc_network_unittests + SRCS + htons_test.cpp + CXX_STANDARD + 20 + DEPENDS + libc.src.network.htons +) diff --git a/libc/test/src/network/htonl_test.cpp b/libc/test/src/network/htonl_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/network/htonl_test.cpp @@ -0,0 +1,22 @@ +//===-- Unittests for htonl -----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/endian.h" +#include "src/network/htonl.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcHtonl, SmokeTest) { + uint32_t original = 0x67452301; + uint32_t swapped = 0x01234567; +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + EXPECT_EQ(__llvm_libc::htonl(original), swapped); +#endif +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + EXPECT_EQ(__llvm_libc::htonl(original), original); +#endif +} diff --git a/libc/test/src/network/htons_test.cpp b/libc/test/src/network/htons_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/network/htons_test.cpp @@ -0,0 +1,22 @@ +//===-- Unittests for htons -----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/endian.h" +#include "src/network/htons.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcHtons, SmokeTest) { + uint16_t original = 0x2301; + uint16_t swapped = 0x0123; +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + EXPECT_EQ(__llvm_libc::htons(original), swapped); +#endif +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + EXPECT_EQ(__llvm_libc::htons(original), original); +#endif +}