[libc] Implement htonl and htons
authorRaman Tenneti <rtenneti@google.com>
Thu, 16 Feb 2023 17:56:36 +0000 (09:56 -0800)
committerRaman Tenneti <rtenneti@google.com>
Thu, 16 Feb 2023 18:12:18 +0000 (10:12 -0800)
Per spec:
* https://pubs.opengroup.org/onlinepubs/9699919799/functions/htonl.html
* https://pubs.opengroup.org/onlinepubs/9699919799/functions/htons.html

Also adds UInt16Type and UInt32Type to spec.td

Co-authored-by: Jeff Bailey <jbailey@google.com>
Reviewed By: sivachandra, jeffbailey, rtenneti

Differential Revision: https://reviews.llvm.org/D143795

17 files changed:
libc/config/linux/aarch64/entrypoints.txt
libc/config/linux/x86_64/entrypoints.txt
libc/config/linux/x86_64/headers.txt
libc/include/CMakeLists.txt
libc/include/arpa/inet.h.def [new file with mode: 0644]
libc/spec/posix.td
libc/spec/spec.td
libc/src/CMakeLists.txt
libc/src/network/CMakeLists.txt [new file with mode: 0644]
libc/src/network/htonl.cpp [new file with mode: 0644]
libc/src/network/htonl.h [new file with mode: 0644]
libc/src/network/htons.cpp [new file with mode: 0644]
libc/src/network/htons.h [new file with mode: 0644]
libc/test/src/CMakeLists.txt
libc/test/src/network/CMakeLists.txt [new file with mode: 0644]
libc/test/src/network/htonl_test.cpp [new file with mode: 0644]
libc/test/src/network/htons_test.cpp [new file with mode: 0644]

index e2826ef..82de499 100644 (file)
@@ -318,6 +318,10 @@ set(TARGET_LIBM_ENTRYPOINTS
 
 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
index e4fe246..6d5aba7 100644 (file)
@@ -331,6 +331,10 @@ if(LLVM_LIBC_FULL_BUILD)
     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
index 3ec9d6a..e943766 100644 (file)
@@ -20,6 +20,8 @@ set(TARGET_PUBLIC_HEADERS
     libc.include.time
     libc.include.unistd
 
+    libc.include.arpa_inet
+
     libc.include.sys_auxv
     libc.include.sys_ioctl
     libc.include.sys_mman
index df61a55..aca05c6 100644 (file)
@@ -68,6 +68,17 @@ add_gen_header(
     .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 (file)
index 0000000..fdd5ae3
--- /dev/null
@@ -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 <inttypes.h>
+
+%%public_api()
+
+#endif // LLVM_LIBC_ARPA_INET_H
index 43cc031..a7e50ca 100644 (file)
@@ -798,6 +798,25 @@ def POSIX : StandardSpec<"POSIX"> {
     ]
   >;
 
+  HeaderSpec ArpaInet = HeaderSpec<
+      "arpa/inet.h",
+      [], // Macros
+      [], // Types
+      [], // Enumerations
+      [
+          FunctionSpec<
+              "htonl",
+              RetValSpec<UInt32Type>,
+              [ArgSpec<UInt32Type>]
+          >,
+          FunctionSpec<
+              "htons",
+              RetValSpec<UInt16Type>,
+              [ArgSpec<UInt16Type>]
+          >,
+      ]
+  >;
+
   HeaderSpec PThread = HeaderSpec<
     "pthread.h",
     [], // Macros
@@ -1260,6 +1279,7 @@ def POSIX : StandardSpec<"POSIX"> {
   >;
 
   let Headers = [
+    ArpaInet,
     CType,
     Dirent,
     Errno,
index 017056d..87bafb0 100644 (file)
@@ -64,6 +64,9 @@ def LongDoublePtr : PtrType<LongDoubleType>;
 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<OffTType>;
 def SSizeTType : NamedType<"ssize_t">;
index 32d557a..59e7d06 100644 (file)
@@ -24,6 +24,7 @@ if(NOT LLVM_LIBC_FULL_BUILD)
 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 (file)
index 0000000..ea5101e
--- /dev/null
@@ -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.cpp b/libc/src/network/htonl.cpp
new file mode 100644 (file)
index 0000000..983fcad
--- /dev/null
@@ -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/htonl.h b/libc/src/network/htonl.h
new file mode 100644 (file)
index 0000000..eab5648
--- /dev/null
@@ -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 <stdint.h>
+
+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/htons.cpp b/libc/src/network/htons.cpp
new file mode 100644 (file)
index 0000000..1d2c6bf
--- /dev/null
@@ -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/src/network/htons.h b/libc/src/network/htons.h
new file mode 100644 (file)
index 0000000..7b61006
--- /dev/null
@@ -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 <stdint.h>
+
+namespace __llvm_libc {
+
+uint16_t htons(uint16_t hostlong);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_NETWORK_HTONS_H
index 1ae1886..bf992ce 100644 (file)
@@ -50,6 +50,7 @@ endif()
 
 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 (file)
index 0000000..ed75dc4
--- /dev/null
@@ -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 (file)
index 0000000..66ffc8b
--- /dev/null
@@ -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 (file)
index 0000000..786f488
--- /dev/null
@@ -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
+}