Skip to content

Commit 81e3e7e

Browse files
[libc] [search] implement hcreate(_r)/hsearch(_r)/hdestroy(_r) (#73469)
This patch implements `hcreate(_r)/hsearch(_r)/hdestroy(_r)` as specified in https://man7.org/linux/man-pages/man3/hsearch.3.html. Notice that `neon/asimd` extension is not yet added in this patch. - The implementation is largely simplified from rust's [`hashbrown`](https://github.com/rust-lang/hashbrown/blob/master/src/raw/mod.rs) as we only consider fix-sized insertion-only hashtables. Technical details are provided in code comments. - This patch also contains a portable string hash function, which is derived from [`aHash`](https://github.com/tkaitchuck/aHash)'s fallback routine. Not using any SIMD acceleration, it has a good enough quality (passing all SMHasher tests) and is not too bad in speed. - Some general functionalities are added, such as `memory_size`, `offset_to`(alignment), `next_power_of_two`, `is_power_of_two`. `ctz/clz` are extended to support shorter integers.
1 parent f7247d5 commit 81e3e7e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+2223
-2
lines changed

libc/cmake/modules/LLVMLibCFlagRules.cmake

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ endfunction(get_fq_dep_list_without_flag)
132132
# Special flags
133133
set(FMA_OPT_FLAG "FMA_OPT")
134134
set(ROUND_OPT_FLAG "ROUND_OPT")
135+
# SSE2 is the baseline for x86_64, so we add a negative flag to disable it if needed.
136+
set(DISABLE_SSE2_OPT_FLAG "DISABLE_SSE2_OPT")
135137

136138
# Skip FMA_OPT flag for targets that don't support fma.
137139
if(NOT((LIBC_TARGET_ARCHITECTURE_IS_X86 AND (LIBC_CPU_FEATURES MATCHES "FMA")) OR
@@ -143,3 +145,8 @@ endif()
143145
if(NOT(LIBC_TARGET_ARCHITECTURE_IS_X86 AND (LIBC_CPU_FEATURES MATCHES "SSE4_2")))
144146
set(SKIP_FLAG_EXPANSION_ROUND_OPT TRUE)
145147
endif()
148+
149+
# Skip DISABLE_SSE2_OPT flag for targets that don't support SSE2.
150+
if(NOT(LIBC_TARGET_ARCHITECTURE_IS_X86 AND (LIBC_CPU_FEATURES MATCHES "SSE2")))
151+
set(SKIP_FLAG_EXPANSION_DISABLE_SSE2_OPT TRUE)
152+
endif()

libc/cmake/modules/LLVMLibCObjectRules.cmake

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@ function(_get_common_compile_options output_var flags)
1818
set(ADD_SSE4_2_FLAG TRUE)
1919
endif()
2020

21+
list(FIND flags ${DISABLE_SSE2_OPT_FLAG} no_sse2)
22+
if(${no_sse2} LESS 0)
23+
list(FIND flags "${DISABLE_SSE2_OPT_FLAG}__ONLY" no_sse2)
24+
endif()
25+
if((${no_sse2} GREATER -1) AND (LIBC_CPU_FEATURES MATCHES "SSE2"))
26+
set(DISABLE_SSE2_FLAG TRUE)
27+
endif()
28+
2129
set(compile_options ${LIBC_COMPILE_OPTIONS_DEFAULT} ${ARGN})
2230
if(LLVM_COMPILER_IS_GCC_COMPATIBLE)
2331
list(APPEND compile_options "-fpie")
@@ -58,12 +66,18 @@ function(_get_common_compile_options output_var flags)
5866
if(ADD_SSE4_2_FLAG)
5967
list(APPEND compile_options "-msse4.2")
6068
endif()
69+
if(DISABLE_SSE2_FLAG)
70+
list(APPEND compile_options "-mno-sse2")
71+
endif()
6172
elseif(MSVC)
6273
list(APPEND compile_options "/EHs-c-")
6374
list(APPEND compile_options "/GR-")
6475
if(ADD_FMA_FLAG)
6576
list(APPEND compile_options "/arch:AVX2")
6677
endif()
78+
if(DISABLE_SSE2_FLAG)
79+
list(APPEND compile_options "/arch:SSE")
80+
endif()
6781
endif()
6882
if (LIBC_TARGET_ARCHITECTURE_IS_GPU)
6983
list(APPEND compile_options "-nogpulib")

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,14 @@ set(TARGET_LIBC_ENTRYPOINTS
130130
#libc.src.stdio.scanf
131131
#libc.src.stdio.fscanf
132132

133+
# search.h entrypoints
134+
libc.src.search.hcreate
135+
libc.src.search.hcreate_r
136+
libc.src.search.hsearch
137+
libc.src.search.hsearch_r
138+
libc.src.search.hdestroy
139+
libc.src.search.hdestroy_r
140+
133141
# sys/mman.h entrypoints
134142
libc.src.sys.mman.madvise
135143
libc.src.sys.mman.mmap

libc/config/linux/aarch64/headers.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ set(TARGET_PUBLIC_HEADERS
1212
libc.include.stdlib
1313
libc.include.string
1414
libc.include.strings
15+
libc.include.search
1516
libc.include.sys_mman
1617
libc.include.sys_socket
1718
libc.include.sys_syscall

libc/config/linux/api.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,3 +248,7 @@ def TermiosAPI : PublicAPI<"termios.h"> {
248248
def SetJmpAPI : PublicAPI<"setjmp.h"> {
249249
let Types = ["jmp_buf"];
250250
}
251+
252+
def SearchAPI : PublicAPI<"search.h"> {
253+
let Types = ["ACTION", "ENTRY", "struct hsearch_data"];
254+
}

libc/config/linux/arm/entrypoints.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@ set(TARGET_LIBC_ENTRYPOINTS
8989
libc.src.stdlib.strtoul
9090
libc.src.stdlib.strtoull
9191

92+
# search.h entrypoints
93+
libc.src.search.hcreate
94+
libc.src.search.hcreate_r
95+
libc.src.search.hsearch
96+
libc.src.search.hsearch_r
97+
libc.src.search.hdestroy
98+
libc.src.search.hdestroy_r
99+
92100
# sys/mman.h entrypoints
93101
libc.src.sys.mman.mmap
94102
libc.src.sys.mman.munmap

libc/config/linux/arm/headers.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ set(TARGET_PUBLIC_HEADERS
77
libc.include.stdlib
88
libc.include.string
99
libc.include.strings
10+
libc.include.search
1011
)

libc/config/linux/riscv/entrypoints.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,14 @@ set(TARGET_LIBC_ENTRYPOINTS
136136
libc.src.stdio.scanf
137137
libc.src.stdio.fscanf
138138

139+
# search.h entrypoints
140+
libc.src.search.hcreate
141+
libc.src.search.hcreate_r
142+
libc.src.search.hsearch
143+
libc.src.search.hsearch_r
144+
libc.src.search.hdestroy
145+
libc.src.search.hdestroy_r
146+
139147
# sys/mman.h entrypoints
140148
libc.src.sys.mman.madvise
141149
libc.src.sys.mman.mmap

libc/config/linux/riscv/headers.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ set(TARGET_PUBLIC_HEADERS
1717
libc.include.stdlib
1818
libc.include.string
1919
libc.include.strings
20+
libc.include.search
2021
libc.include.termios
2122
libc.include.threads
2223
libc.include.time

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,14 @@ if(LLVM_LIBC_FULL_BUILD)
497497
libc.src.spawn.posix_spawn_file_actions_destroy
498498
libc.src.spawn.posix_spawn_file_actions_init
499499

500+
# search.h entrypoints
501+
libc.src.search.hcreate
502+
libc.src.search.hcreate_r
503+
libc.src.search.hsearch
504+
libc.src.search.hsearch_r
505+
libc.src.search.hdestroy
506+
libc.src.search.hdestroy_r
507+
500508
# threads.h entrypoints
501509
libc.src.threads.call_once
502510
libc.src.threads.cnd_broadcast

libc/config/linux/x86_64/headers.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ set(TARGET_PUBLIC_HEADERS
1717
libc.include.stdlib
1818
libc.include.string
1919
libc.include.strings
20+
libc.include.search
2021
libc.include.termios
2122
libc.include.threads
2223
libc.include.time

libc/include/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,18 @@ add_gen_header(
133133
.llvm-libc-types.size_t
134134
)
135135

136+
add_gen_header(
137+
search
138+
DEF_FILE search.h.def
139+
GEN_HDR search.h
140+
DEPENDS
141+
.llvm_libc_common_h
142+
.llvm-libc-types.ACTION
143+
.llvm-libc-types.ENTRY
144+
.llvm-libc-types.struct_hsearch_data
145+
.llvm-libc-types.size_t
146+
)
147+
136148
add_gen_header(
137149
time
138150
DEF_FILE time.h.def

libc/include/llvm-libc-types/ACTION.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//===-- Definition of ACTION type -----------------------------------------===//
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_TYPES_ACTION_H__
10+
#define __LLVM_LIBC_TYPES_ACTION_H__
11+
12+
typedef enum { FIND, ENTER } ACTION;
13+
14+
#endif // __LLVM_LIBC_TYPES_ACTION_H__

libc/include/llvm-libc-types/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,6 @@ add_header(wint_t HDR wint_t.h)
9191
add_header(sa_family_t HDR sa_family_t.h)
9292
add_header(struct_sockaddr HDR struct_sockaddr.h)
9393
add_header(rpc_opcodes_t HDR rpc_opcodes_t.h)
94+
add_header(ACTION HDR ACTION.h)
95+
add_header(ENTRY HDR ENTRY.h)
96+
add_header(struct_hsearch_data HDR struct_hsearch_data.h)

libc/include/llvm-libc-types/ENTRY.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//===-- Definition of ENTRY type ------------------------------------------===//
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_TYPES_ENTRY_H__
10+
#define __LLVM_LIBC_TYPES_ENTRY_H__
11+
12+
typedef struct {
13+
char *key;
14+
void *data;
15+
} ENTRY;
16+
17+
#endif // __LLVM_LIBC_TYPES_ENTRY_H__
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//===-- Definition of type struct hsearch_data ----------------------------===//
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_TYPES_STRUCT_HSEARCH_DATA_H__
10+
#define __LLVM_LIBC_TYPES_STRUCT_HSEARCH_DATA_H__
11+
12+
struct hsearch_data {
13+
void *__opaque;
14+
unsigned int __unused[2];
15+
};
16+
17+
#endif // __LLVM_LIBC_TYPES_STRUCT_HSEARCH_DATA_H__

libc/include/search.h.def

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//===-- POSIX header search.h ---------------------------------------------===//
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_SEARCH_H
10+
#define LLVM_LIBC_SEARCH_H
11+
12+
#include <__llvm-libc-common.h>
13+
#define __need_size_t
14+
#include <stddef.h>
15+
16+
%%public_api()
17+
18+
#endif // LLVM_LIBC_SEARCH_H

libc/spec/gnu_ext.td

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ def CpuSetPtr : PtrType<CpuSetT>;
33
def ConstCpuSetPtr : ConstType<CpuSetPtr>;
44

55
def QSortRCompareT : NamedType<"__qsortrcompare_t">;
6+
def StructHsearchData : NamedType<"struct hsearch_data">;
7+
def StructHsearchDataPtr : PtrType<StructHsearchData>;
68

79
def GnuExtensions : StandardSpec<"GNUExtensions"> {
810
NamedType CookieIOFunctionsT = NamedType<"cookie_io_functions_t">;
@@ -54,7 +56,6 @@ def GnuExtensions : StandardSpec<"GNUExtensions"> {
5456
>,
5557
]
5658
>;
57-
5859
HeaderSpec String = HeaderSpec<
5960
"string.h",
6061
[], // Macros
@@ -89,6 +90,42 @@ def GnuExtensions : StandardSpec<"GNUExtensions"> {
8990
]
9091
>;
9192

93+
HeaderSpec Search = HeaderSpec<
94+
"search.h",
95+
[], // Macros
96+
[
97+
StructHsearchData
98+
],
99+
[], // Enumerations
100+
[
101+
FunctionSpec<
102+
"hcreate_r",
103+
RetValSpec<IntType>,
104+
[
105+
ArgSpec<SizeTType>,
106+
ArgSpec<StructHsearchDataPtr>
107+
]
108+
>,
109+
FunctionSpec<
110+
"hdestroy_r",
111+
RetValSpec<VoidType>,
112+
[
113+
ArgSpec<StructHsearchDataPtr>
114+
]
115+
>,
116+
FunctionSpec<
117+
"hsearch_r",
118+
RetValSpec<IntType>,
119+
[
120+
ArgSpec<EntryType>,
121+
ArgSpec<ActionType>,
122+
ArgSpec<EntryTypePtrPtr>,
123+
ArgSpec<StructHsearchDataPtr>
124+
]
125+
>,
126+
]
127+
>;
128+
92129
HeaderSpec FEnv = HeaderSpec<
93130
"fenv.h",
94131
[], // Macros
@@ -243,6 +280,7 @@ def GnuExtensions : StandardSpec<"GNUExtensions"> {
243280
StdIO,
244281
StdLib,
245282
String,
283+
Search,
246284
UniStd,
247285
];
248286
}

libc/spec/posix.td

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1269,6 +1269,38 @@ def POSIX : StandardSpec<"POSIX"> {
12691269
]
12701270
>;
12711271

1272+
HeaderSpec Search = HeaderSpec<
1273+
"search.h",
1274+
[], // Macros
1275+
[
1276+
ActionType,
1277+
EntryType
1278+
], // Types
1279+
[], // Enumerations
1280+
[
1281+
FunctionSpec<
1282+
"hcreate",
1283+
RetValSpec<IntType>,
1284+
[
1285+
ArgSpec<SizeTType>
1286+
]
1287+
>,
1288+
FunctionSpec<
1289+
"hdestroy",
1290+
RetValSpec<VoidType>,
1291+
[] // Args
1292+
>,
1293+
FunctionSpec<
1294+
"hsearch",
1295+
RetValSpec<EntryTypePtr>,
1296+
[
1297+
ArgSpec<EntryType>,
1298+
ArgSpec<ActionType>
1299+
]
1300+
>,
1301+
]
1302+
>;
1303+
12721304
HeaderSpec Termios = HeaderSpec<
12731305
"termios.h",
12741306
[
@@ -1414,6 +1446,7 @@ def POSIX : StandardSpec<"POSIX"> {
14141446
Time,
14151447
Termios,
14161448
UniStd,
1417-
String
1449+
String,
1450+
Search,
14181451
];
14191452
}

libc/spec/spec.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,11 @@ def SuSecondsT : NamedType<"suseconds_t">;
140140
//added because __assert_fail needs it.
141141
def UnsignedType : NamedType<"unsigned">;
142142

143+
def ActionType : NamedType<"ACTION">;
144+
def EntryType : NamedType<"ENTRY">;
145+
def EntryTypePtr : PtrType<EntryType>;
146+
def EntryTypePtrPtr : PtrType<EntryTypePtr>;
147+
143148
class Macro<string name> {
144149
string Name = name;
145150
}

libc/src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ add_subdirectory(signal)
3535
add_subdirectory(spawn)
3636
add_subdirectory(threads)
3737
add_subdirectory(time)
38+
add_subdirectory(search)

0 commit comments

Comments
 (0)