Skip to content

Commit a5588b6

Browse files
authored
[libc] implement strings/ffs (#129892)
This patch adds the `strings/ffs` function. ref: https://pubs.opengroup.org/onlinepubs/9799919799/functions/ffs.html Closes: #122054.
1 parent 15869a8 commit a5588b6

File tree

14 files changed

+318
-0
lines changed

14 files changed

+318
-0
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ set(TARGET_LIBC_ENTRYPOINTS
9393
libc.src.strings.bcmp
9494
libc.src.strings.bcopy
9595
libc.src.strings.bzero
96+
libc.src.strings.ffs
97+
libc.src.strings.ffsl
98+
libc.src.strings.ffsll
9699
libc.src.strings.index
97100
libc.src.strings.rindex
98101
libc.src.strings.strcasecmp

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ set(TARGET_LIBC_ENTRYPOINTS
9393
libc.src.strings.bcmp
9494
libc.src.strings.bcopy
9595
libc.src.strings.bzero
96+
libc.src.strings.ffs
97+
libc.src.strings.ffsl
98+
libc.src.strings.ffsll
9699
libc.src.strings.index
97100
libc.src.strings.rindex
98101
libc.src.strings.strcasecmp

libc/include/strings.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,24 @@ functions:
2929
arguments:
3030
- type: void *
3131
- type: size_t
32+
- name: ffs
33+
standards:
34+
- POSIX
35+
return_type: int
36+
arguments:
37+
- type: int
38+
- name: ffsl
39+
standards:
40+
- POSIX
41+
return_type: int
42+
arguments:
43+
- type: long
44+
- name: ffsll
45+
standards:
46+
- POSIX
47+
return_type: int
48+
arguments:
49+
- type: long long
3250
- name: index
3351
standards:
3452
- BSDExtensions

libc/src/strings/CMakeLists.txt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,36 @@ add_entrypoint_object(
5454
bcopy.h
5555
)
5656

57+
add_entrypoint_object(
58+
ffs
59+
SRCS
60+
ffs.cpp
61+
HDRS
62+
ffs.h
63+
DEPENDS
64+
libc.src.__support.math_extras
65+
)
66+
67+
add_entrypoint_object(
68+
ffsl
69+
SRCS
70+
ffsl.cpp
71+
HDRS
72+
ffsl.h
73+
DEPENDS
74+
libc.src.__support.math_extras
75+
)
76+
77+
add_entrypoint_object(
78+
ffsll
79+
SRCS
80+
ffsll.cpp
81+
HDRS
82+
ffsll.h
83+
DEPENDS
84+
libc.src.__support.math_extras
85+
)
86+
5787
add_entrypoint_object(
5888
index
5989
SRCS

libc/src/strings/ffs.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation of ffs ---------------------------------------------===//
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/strings/ffs.h"
10+
#include "src/__support/common.h"
11+
#include "src/__support/macros/config.h"
12+
#include "src/__support/math_extras.h"
13+
14+
namespace LIBC_NAMESPACE_DECL {
15+
16+
LLVM_LIBC_FUNCTION(int, ffs, (int i)) {
17+
return first_trailing_one(static_cast<unsigned>(i));
18+
}
19+
20+
} // namespace LIBC_NAMESPACE_DECL

libc/src/strings/ffs.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for ffs ---------------------------*- 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_STRINGS_FFS_H
10+
#define LLVM_LIBC_SRC_STRINGS_FFS_H
11+
12+
#include "src/__support/macros/config.h"
13+
14+
namespace LIBC_NAMESPACE_DECL {
15+
16+
int ffs(int i);
17+
18+
} // namespace LIBC_NAMESPACE_DECL
19+
20+
#endif // LLVM_LIBC_SRC_STRINGS_FFS_H

libc/src/strings/ffsl.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation of ffsl --------------------------------------------===//
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/strings/ffsl.h"
10+
#include "src/__support/common.h"
11+
#include "src/__support/macros/config.h"
12+
#include "src/__support/math_extras.h"
13+
14+
namespace LIBC_NAMESPACE_DECL {
15+
16+
LLVM_LIBC_FUNCTION(int, ffsl, (long i)) {
17+
return first_trailing_one(static_cast<unsigned long>(i));
18+
}
19+
20+
} // namespace LIBC_NAMESPACE_DECL

libc/src/strings/ffsl.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for ffsl --------------------------*- 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_STRINGS_FFSL_H
10+
#define LLVM_LIBC_SRC_STRINGS_FFSL_H
11+
12+
#include "src/__support/macros/config.h"
13+
14+
namespace LIBC_NAMESPACE_DECL {
15+
16+
int ffsl(long i);
17+
18+
} // namespace LIBC_NAMESPACE_DECL
19+
20+
#endif // LLVM_LIBC_SRC_STRINGS_FFSL_H

libc/src/strings/ffsll.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation of ffsll -------------------------------------------===//
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/strings/ffsll.h"
10+
#include "src/__support/common.h"
11+
#include "src/__support/macros/config.h"
12+
#include "src/__support/math_extras.h"
13+
14+
namespace LIBC_NAMESPACE_DECL {
15+
16+
LLVM_LIBC_FUNCTION(int, ffsll, (long long i)) {
17+
return first_trailing_one(static_cast<unsigned long long>(i));
18+
}
19+
20+
} // namespace LIBC_NAMESPACE_DECL

libc/src/strings/ffsll.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for ffsll -------------------------*- 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_STRINGS_FFSLL_H
10+
#define LLVM_LIBC_SRC_STRINGS_FFSLL_H
11+
12+
#include "src/__support/macros/config.h"
13+
14+
namespace LIBC_NAMESPACE_DECL {
15+
16+
int ffsll(long long i);
17+
18+
} // namespace LIBC_NAMESPACE_DECL
19+
20+
#endif // LLVM_LIBC_SRC_STRINGS_FFSLL_H

libc/test/src/strings/CMakeLists.txt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,36 @@ add_libc_test(
1212
LibcMemoryHelpers
1313
)
1414

15+
add_libc_test(
16+
ffs_test
17+
SUITE
18+
libc-strings-tests
19+
SRCS
20+
ffs_test.cpp
21+
DEPENDS
22+
libc.src.strings.ffs
23+
)
24+
25+
add_libc_test(
26+
ffsl_test
27+
SUITE
28+
libc-strings-tests
29+
SRCS
30+
ffsl_test.cpp
31+
DEPENDS
32+
libc.src.strings.ffsl
33+
)
34+
35+
add_libc_test(
36+
ffsll_test
37+
SUITE
38+
libc-strings-tests
39+
SRCS
40+
ffsll_test.cpp
41+
DEPENDS
42+
libc.src.strings.ffsll
43+
)
44+
1545
add_libc_test(
1646
index_test
1747
SUITE

libc/test/src/strings/ffs_test.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//===-- Unittests for ffs -------------------------------------------------===//
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/strings/ffs.h"
10+
11+
#include "src/__support/macros/config.h"
12+
#include "test/UnitTest/Test.h"
13+
14+
namespace LIBC_NAMESPACE_DECL {
15+
16+
TEST(LlvmLibcFfsTest, SimpleFfs) {
17+
ASSERT_EQ(ffs(0x00000000), 0);
18+
ASSERT_EQ(ffs(0x00000001), 1);
19+
ASSERT_EQ(ffs(0x00000020), 6);
20+
ASSERT_EQ(ffs(0x00000400), 11);
21+
ASSERT_EQ(ffs(0x00008000), 16);
22+
ASSERT_EQ(ffs(0x00010000), 17);
23+
ASSERT_EQ(ffs(0x00200000), 22);
24+
ASSERT_EQ(ffs(0x04000000), 27);
25+
ASSERT_EQ(ffs(0x80000000), 32);
26+
ASSERT_EQ(ffs(0xfbe71), 1);
27+
ASSERT_EQ(ffs(0xfbe70), 5);
28+
ASSERT_EQ(ffs(0x10), 5);
29+
ASSERT_EQ(ffs(0x100), 9);
30+
}
31+
32+
} // namespace LIBC_NAMESPACE_DECL

libc/test/src/strings/ffsl_test.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//===-- Unittests for ffsl ------------------------------------------------===//
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/strings/ffsl.h"
10+
11+
#include "src/__support/macros/config.h"
12+
#include "test/UnitTest/Test.h"
13+
14+
namespace LIBC_NAMESPACE_DECL {
15+
16+
TEST(LlvmLibcFfslTest, SimpleFfsl) {
17+
ASSERT_EQ(ffsl(0x00000000L), 0);
18+
ASSERT_EQ(ffsl(0x00000001L), 1);
19+
ASSERT_EQ(ffsl(0x00000020L), 6);
20+
ASSERT_EQ(ffsl(0x00000400L), 11);
21+
ASSERT_EQ(ffsl(0x00008000L), 16);
22+
ASSERT_EQ(ffsl(0x00010000L), 17);
23+
ASSERT_EQ(ffsl(0x00200000L), 22);
24+
ASSERT_EQ(ffsl(0x04000000L), 27);
25+
ASSERT_EQ(ffsl(0x80000000L), 32);
26+
#ifdef __LP64__
27+
ASSERT_EQ(ffsl(0x0000000100000000L), 33);
28+
ASSERT_EQ(ffsl(0x0000002000000000L), 38);
29+
ASSERT_EQ(ffsl(0x0000040000000000L), 43);
30+
ASSERT_EQ(ffsl(0x0000800000000000L), 48);
31+
ASSERT_EQ(ffsl(0x0001000000000000L), 49);
32+
ASSERT_EQ(ffsl(0x0020000000000000L), 54);
33+
ASSERT_EQ(ffsl(0x0400000000000000L), 59);
34+
ASSERT_EQ(ffsl(0x8000000000000000L), 64);
35+
#endif
36+
ASSERT_EQ(ffsl(0xfbe71L), 1);
37+
ASSERT_EQ(ffsl(0xfbe70L), 5);
38+
ASSERT_EQ(ffsl(0x10L), 5);
39+
ASSERT_EQ(ffsl(0x100L), 9);
40+
}
41+
42+
} // namespace LIBC_NAMESPACE_DECL

libc/test/src/strings/ffsll_test.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//===-- Unittests for ffsll -----------------------------------------------===//
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/strings/ffsll.h"
10+
11+
#include "src/__support/macros/config.h"
12+
#include "test/UnitTest/Test.h"
13+
14+
namespace LIBC_NAMESPACE_DECL {
15+
16+
TEST(LlvmLibcFfsllTest, SimpleFfsll) {
17+
ASSERT_EQ(ffsll(0x0000000000000000LL), 0);
18+
ASSERT_EQ(ffsll(0x0000000000000001LL), 1);
19+
ASSERT_EQ(ffsll(0x0000000000000020LL), 6);
20+
ASSERT_EQ(ffsll(0x0000000000000400LL), 11);
21+
ASSERT_EQ(ffsll(0x0000000000008000LL), 16);
22+
ASSERT_EQ(ffsll(0x0000000000010000LL), 17);
23+
ASSERT_EQ(ffsll(0x0000000000200000LL), 22);
24+
ASSERT_EQ(ffsll(0x0000000004000000LL), 27);
25+
ASSERT_EQ(ffsll(0x0000000080000000LL), 32);
26+
ASSERT_EQ(ffsll(0x0000000100000000LL), 33);
27+
ASSERT_EQ(ffsll(0x0000002000000000LL), 38);
28+
ASSERT_EQ(ffsll(0x0000040000000000LL), 43);
29+
ASSERT_EQ(ffsll(0x0000800000000000LL), 48);
30+
ASSERT_EQ(ffsll(0x0001000000000000LL), 49);
31+
ASSERT_EQ(ffsll(0x0020000000000000LL), 54);
32+
ASSERT_EQ(ffsll(0x0400000000000000LL), 59);
33+
ASSERT_EQ(ffsll(0x8000000000000000LL), 64);
34+
ASSERT_EQ(ffsll(0xfbe71LL), 1);
35+
ASSERT_EQ(ffsll(0xfbe70LL), 5);
36+
ASSERT_EQ(ffsll(0x10LL), 5);
37+
ASSERT_EQ(ffsll(0x100LL), 9);
38+
}
39+
40+
} // namespace LIBC_NAMESPACE_DECL

0 commit comments

Comments
 (0)