diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index 6c2be4d3b0b99..c7beb3ef3fdfc 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -93,6 +93,9 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.strings.bcmp libc.src.strings.bcopy libc.src.strings.bzero + libc.src.strings.ffs + libc.src.strings.ffsl + libc.src.strings.ffsll libc.src.strings.index libc.src.strings.rindex libc.src.strings.strcasecmp diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 779654422e35b..12dc87bf945fd 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -93,6 +93,9 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.strings.bcmp libc.src.strings.bcopy libc.src.strings.bzero + libc.src.strings.ffs + libc.src.strings.ffsl + libc.src.strings.ffsll libc.src.strings.index libc.src.strings.rindex libc.src.strings.strcasecmp diff --git a/libc/include/strings.yaml b/libc/include/strings.yaml index b6aa8f6d60b27..802f6533585f8 100644 --- a/libc/include/strings.yaml +++ b/libc/include/strings.yaml @@ -29,6 +29,24 @@ functions: arguments: - type: void * - type: size_t + - name: ffs + standards: + - POSIX + return_type: int + arguments: + - type: int + - name: ffsl + standards: + - POSIX + return_type: int + arguments: + - type: long + - name: ffsll + standards: + - POSIX + return_type: int + arguments: + - type: long long - name: index standards: - BSDExtensions diff --git a/libc/src/strings/CMakeLists.txt b/libc/src/strings/CMakeLists.txt index 5e84c7be1f7d6..6d86680e8e71f 100644 --- a/libc/src/strings/CMakeLists.txt +++ b/libc/src/strings/CMakeLists.txt @@ -54,6 +54,36 @@ add_entrypoint_object( bcopy.h ) +add_entrypoint_object( + ffs + SRCS + ffs.cpp + HDRS + ffs.h + DEPENDS + libc.src.__support.math_extras +) + +add_entrypoint_object( + ffsl + SRCS + ffsl.cpp + HDRS + ffsl.h + DEPENDS + libc.src.__support.math_extras +) + +add_entrypoint_object( + ffsll + SRCS + ffsll.cpp + HDRS + ffsll.h + DEPENDS + libc.src.__support.math_extras +) + add_entrypoint_object( index SRCS diff --git a/libc/src/strings/ffs.cpp b/libc/src/strings/ffs.cpp new file mode 100644 index 0000000000000..5e1efafeab56a --- /dev/null +++ b/libc/src/strings/ffs.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of ffs ---------------------------------------------===// +// +// 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/strings/ffs.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" +#include "src/__support/math_extras.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(int, ffs, (int i)) { + return first_trailing_one(static_cast(i)); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/strings/ffs.h b/libc/src/strings/ffs.h new file mode 100644 index 0000000000000..bf43c43caedb2 --- /dev/null +++ b/libc/src/strings/ffs.h @@ -0,0 +1,20 @@ +//===-- Implementation header for ffs ---------------------------*- 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_STRINGS_FFS_H +#define LLVM_LIBC_SRC_STRINGS_FFS_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +int ffs(int i); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_STRINGS_FFS_H diff --git a/libc/src/strings/ffsl.cpp b/libc/src/strings/ffsl.cpp new file mode 100644 index 0000000000000..b1b25598e405b --- /dev/null +++ b/libc/src/strings/ffsl.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of ffsl --------------------------------------------===// +// +// 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/strings/ffsl.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" +#include "src/__support/math_extras.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(int, ffsl, (long i)) { + return first_trailing_one(static_cast(i)); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/strings/ffsl.h b/libc/src/strings/ffsl.h new file mode 100644 index 0000000000000..1feca010b2ebb --- /dev/null +++ b/libc/src/strings/ffsl.h @@ -0,0 +1,20 @@ +//===-- Implementation header for ffsl --------------------------*- 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_STRINGS_FFSL_H +#define LLVM_LIBC_SRC_STRINGS_FFSL_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +int ffsl(long i); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_STRINGS_FFSL_H diff --git a/libc/src/strings/ffsll.cpp b/libc/src/strings/ffsll.cpp new file mode 100644 index 0000000000000..be16e81a54711 --- /dev/null +++ b/libc/src/strings/ffsll.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of ffsll -------------------------------------------===// +// +// 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/strings/ffsll.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" +#include "src/__support/math_extras.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(int, ffsll, (long long i)) { + return first_trailing_one(static_cast(i)); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/strings/ffsll.h b/libc/src/strings/ffsll.h new file mode 100644 index 0000000000000..f059b8ab89b4e --- /dev/null +++ b/libc/src/strings/ffsll.h @@ -0,0 +1,20 @@ +//===-- Implementation header for ffsll -------------------------*- 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_STRINGS_FFSLL_H +#define LLVM_LIBC_SRC_STRINGS_FFSLL_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +int ffsll(long long i); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_STRINGS_FFSLL_H diff --git a/libc/test/src/strings/CMakeLists.txt b/libc/test/src/strings/CMakeLists.txt index 10f96b8531f68..baa22bb449c6c 100644 --- a/libc/test/src/strings/CMakeLists.txt +++ b/libc/test/src/strings/CMakeLists.txt @@ -12,6 +12,36 @@ add_libc_test( LibcMemoryHelpers ) +add_libc_test( + ffs_test + SUITE + libc-strings-tests + SRCS + ffs_test.cpp + DEPENDS + libc.src.strings.ffs +) + +add_libc_test( + ffsl_test + SUITE + libc-strings-tests + SRCS + ffsl_test.cpp + DEPENDS + libc.src.strings.ffsl +) + +add_libc_test( + ffsll_test + SUITE + libc-strings-tests + SRCS + ffsll_test.cpp + DEPENDS + libc.src.strings.ffsll +) + add_libc_test( index_test SUITE diff --git a/libc/test/src/strings/ffs_test.cpp b/libc/test/src/strings/ffs_test.cpp new file mode 100644 index 0000000000000..17cd412b2df05 --- /dev/null +++ b/libc/test/src/strings/ffs_test.cpp @@ -0,0 +1,32 @@ +//===-- Unittests for ffs -------------------------------------------------===// +// +// 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/strings/ffs.h" + +#include "src/__support/macros/config.h" +#include "test/UnitTest/Test.h" + +namespace LIBC_NAMESPACE_DECL { + +TEST(LlvmLibcFfsTest, SimpleFfs) { + ASSERT_EQ(ffs(0x00000000), 0); + ASSERT_EQ(ffs(0x00000001), 1); + ASSERT_EQ(ffs(0x00000020), 6); + ASSERT_EQ(ffs(0x00000400), 11); + ASSERT_EQ(ffs(0x00008000), 16); + ASSERT_EQ(ffs(0x00010000), 17); + ASSERT_EQ(ffs(0x00200000), 22); + ASSERT_EQ(ffs(0x04000000), 27); + ASSERT_EQ(ffs(0x80000000), 32); + ASSERT_EQ(ffs(0xfbe71), 1); + ASSERT_EQ(ffs(0xfbe70), 5); + ASSERT_EQ(ffs(0x10), 5); + ASSERT_EQ(ffs(0x100), 9); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/test/src/strings/ffsl_test.cpp b/libc/test/src/strings/ffsl_test.cpp new file mode 100644 index 0000000000000..cf5c32f2fec6b --- /dev/null +++ b/libc/test/src/strings/ffsl_test.cpp @@ -0,0 +1,42 @@ +//===-- Unittests for ffsl ------------------------------------------------===// +// +// 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/strings/ffsl.h" + +#include "src/__support/macros/config.h" +#include "test/UnitTest/Test.h" + +namespace LIBC_NAMESPACE_DECL { + +TEST(LlvmLibcFfslTest, SimpleFfsl) { + ASSERT_EQ(ffsl(0x00000000L), 0); + ASSERT_EQ(ffsl(0x00000001L), 1); + ASSERT_EQ(ffsl(0x00000020L), 6); + ASSERT_EQ(ffsl(0x00000400L), 11); + ASSERT_EQ(ffsl(0x00008000L), 16); + ASSERT_EQ(ffsl(0x00010000L), 17); + ASSERT_EQ(ffsl(0x00200000L), 22); + ASSERT_EQ(ffsl(0x04000000L), 27); + ASSERT_EQ(ffsl(0x80000000L), 32); +#ifdef __LP64__ + ASSERT_EQ(ffsl(0x0000000100000000L), 33); + ASSERT_EQ(ffsl(0x0000002000000000L), 38); + ASSERT_EQ(ffsl(0x0000040000000000L), 43); + ASSERT_EQ(ffsl(0x0000800000000000L), 48); + ASSERT_EQ(ffsl(0x0001000000000000L), 49); + ASSERT_EQ(ffsl(0x0020000000000000L), 54); + ASSERT_EQ(ffsl(0x0400000000000000L), 59); + ASSERT_EQ(ffsl(0x8000000000000000L), 64); +#endif + ASSERT_EQ(ffsl(0xfbe71L), 1); + ASSERT_EQ(ffsl(0xfbe70L), 5); + ASSERT_EQ(ffsl(0x10L), 5); + ASSERT_EQ(ffsl(0x100L), 9); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/test/src/strings/ffsll_test.cpp b/libc/test/src/strings/ffsll_test.cpp new file mode 100644 index 0000000000000..bdd7a2ed30f3c --- /dev/null +++ b/libc/test/src/strings/ffsll_test.cpp @@ -0,0 +1,40 @@ +//===-- Unittests for ffsll -----------------------------------------------===// +// +// 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/strings/ffsll.h" + +#include "src/__support/macros/config.h" +#include "test/UnitTest/Test.h" + +namespace LIBC_NAMESPACE_DECL { + +TEST(LlvmLibcFfsllTest, SimpleFfsll) { + ASSERT_EQ(ffsll(0x0000000000000000LL), 0); + ASSERT_EQ(ffsll(0x0000000000000001LL), 1); + ASSERT_EQ(ffsll(0x0000000000000020LL), 6); + ASSERT_EQ(ffsll(0x0000000000000400LL), 11); + ASSERT_EQ(ffsll(0x0000000000008000LL), 16); + ASSERT_EQ(ffsll(0x0000000000010000LL), 17); + ASSERT_EQ(ffsll(0x0000000000200000LL), 22); + ASSERT_EQ(ffsll(0x0000000004000000LL), 27); + ASSERT_EQ(ffsll(0x0000000080000000LL), 32); + ASSERT_EQ(ffsll(0x0000000100000000LL), 33); + ASSERT_EQ(ffsll(0x0000002000000000LL), 38); + ASSERT_EQ(ffsll(0x0000040000000000LL), 43); + ASSERT_EQ(ffsll(0x0000800000000000LL), 48); + ASSERT_EQ(ffsll(0x0001000000000000LL), 49); + ASSERT_EQ(ffsll(0x0020000000000000LL), 54); + ASSERT_EQ(ffsll(0x0400000000000000LL), 59); + ASSERT_EQ(ffsll(0x8000000000000000LL), 64); + ASSERT_EQ(ffsll(0xfbe71LL), 1); + ASSERT_EQ(ffsll(0xfbe70LL), 5); + ASSERT_EQ(ffsll(0x10LL), 5); + ASSERT_EQ(ffsll(0x100LL), 9); +} + +} // namespace LIBC_NAMESPACE_DECL