Skip to content

Commit

Permalink
[libc] [search] implement hcreate(_r)/hsearch(_r)/hdestroy(_r) (#73469)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
SchrodingerZhu committed Nov 29, 2023
1 parent f7247d5 commit 81e3e7e
Show file tree
Hide file tree
Showing 58 changed files with 2,223 additions and 2 deletions.
7 changes: 7 additions & 0 deletions libc/cmake/modules/LLVMLibCFlagRules.cmake
Expand Up @@ -132,6 +132,8 @@ endfunction(get_fq_dep_list_without_flag)
# Special flags
set(FMA_OPT_FLAG "FMA_OPT")
set(ROUND_OPT_FLAG "ROUND_OPT")
# SSE2 is the baseline for x86_64, so we add a negative flag to disable it if needed.
set(DISABLE_SSE2_OPT_FLAG "DISABLE_SSE2_OPT")

# Skip FMA_OPT flag for targets that don't support fma.
if(NOT((LIBC_TARGET_ARCHITECTURE_IS_X86 AND (LIBC_CPU_FEATURES MATCHES "FMA")) OR
Expand All @@ -143,3 +145,8 @@ endif()
if(NOT(LIBC_TARGET_ARCHITECTURE_IS_X86 AND (LIBC_CPU_FEATURES MATCHES "SSE4_2")))
set(SKIP_FLAG_EXPANSION_ROUND_OPT TRUE)
endif()

# Skip DISABLE_SSE2_OPT flag for targets that don't support SSE2.
if(NOT(LIBC_TARGET_ARCHITECTURE_IS_X86 AND (LIBC_CPU_FEATURES MATCHES "SSE2")))
set(SKIP_FLAG_EXPANSION_DISABLE_SSE2_OPT TRUE)
endif()
14 changes: 14 additions & 0 deletions libc/cmake/modules/LLVMLibCObjectRules.cmake
Expand Up @@ -18,6 +18,14 @@ function(_get_common_compile_options output_var flags)
set(ADD_SSE4_2_FLAG TRUE)
endif()

list(FIND flags ${DISABLE_SSE2_OPT_FLAG} no_sse2)
if(${no_sse2} LESS 0)
list(FIND flags "${DISABLE_SSE2_OPT_FLAG}__ONLY" no_sse2)
endif()
if((${no_sse2} GREATER -1) AND (LIBC_CPU_FEATURES MATCHES "SSE2"))
set(DISABLE_SSE2_FLAG TRUE)
endif()

set(compile_options ${LIBC_COMPILE_OPTIONS_DEFAULT} ${ARGN})
if(LLVM_COMPILER_IS_GCC_COMPATIBLE)
list(APPEND compile_options "-fpie")
Expand Down Expand Up @@ -58,12 +66,18 @@ function(_get_common_compile_options output_var flags)
if(ADD_SSE4_2_FLAG)
list(APPEND compile_options "-msse4.2")
endif()
if(DISABLE_SSE2_FLAG)
list(APPEND compile_options "-mno-sse2")
endif()
elseif(MSVC)
list(APPEND compile_options "/EHs-c-")
list(APPEND compile_options "/GR-")
if(ADD_FMA_FLAG)
list(APPEND compile_options "/arch:AVX2")
endif()
if(DISABLE_SSE2_FLAG)
list(APPEND compile_options "/arch:SSE")
endif()
endif()
if (LIBC_TARGET_ARCHITECTURE_IS_GPU)
list(APPEND compile_options "-nogpulib")
Expand Down
8 changes: 8 additions & 0 deletions libc/config/linux/aarch64/entrypoints.txt
Expand Up @@ -130,6 +130,14 @@ set(TARGET_LIBC_ENTRYPOINTS
#libc.src.stdio.scanf
#libc.src.stdio.fscanf

# search.h entrypoints
libc.src.search.hcreate
libc.src.search.hcreate_r
libc.src.search.hsearch
libc.src.search.hsearch_r
libc.src.search.hdestroy
libc.src.search.hdestroy_r

# sys/mman.h entrypoints
libc.src.sys.mman.madvise
libc.src.sys.mman.mmap
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/aarch64/headers.txt
Expand Up @@ -12,6 +12,7 @@ set(TARGET_PUBLIC_HEADERS
libc.include.stdlib
libc.include.string
libc.include.strings
libc.include.search
libc.include.sys_mman
libc.include.sys_socket
libc.include.sys_syscall
Expand Down
4 changes: 4 additions & 0 deletions libc/config/linux/api.td
Expand Up @@ -248,3 +248,7 @@ def TermiosAPI : PublicAPI<"termios.h"> {
def SetJmpAPI : PublicAPI<"setjmp.h"> {
let Types = ["jmp_buf"];
}

def SearchAPI : PublicAPI<"search.h"> {
let Types = ["ACTION", "ENTRY", "struct hsearch_data"];
}
8 changes: 8 additions & 0 deletions libc/config/linux/arm/entrypoints.txt
Expand Up @@ -89,6 +89,14 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.stdlib.strtoul
libc.src.stdlib.strtoull

# search.h entrypoints
libc.src.search.hcreate
libc.src.search.hcreate_r
libc.src.search.hsearch
libc.src.search.hsearch_r
libc.src.search.hdestroy
libc.src.search.hdestroy_r

# sys/mman.h entrypoints
libc.src.sys.mman.mmap
libc.src.sys.mman.munmap
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/arm/headers.txt
Expand Up @@ -7,4 +7,5 @@ set(TARGET_PUBLIC_HEADERS
libc.include.stdlib
libc.include.string
libc.include.strings
libc.include.search
)
8 changes: 8 additions & 0 deletions libc/config/linux/riscv/entrypoints.txt
Expand Up @@ -136,6 +136,14 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.stdio.scanf
libc.src.stdio.fscanf

# search.h entrypoints
libc.src.search.hcreate
libc.src.search.hcreate_r
libc.src.search.hsearch
libc.src.search.hsearch_r
libc.src.search.hdestroy
libc.src.search.hdestroy_r

# sys/mman.h entrypoints
libc.src.sys.mman.madvise
libc.src.sys.mman.mmap
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/riscv/headers.txt
Expand Up @@ -17,6 +17,7 @@ set(TARGET_PUBLIC_HEADERS
libc.include.stdlib
libc.include.string
libc.include.strings
libc.include.search
libc.include.termios
libc.include.threads
libc.include.time
Expand Down
8 changes: 8 additions & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Expand Up @@ -497,6 +497,14 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.spawn.posix_spawn_file_actions_destroy
libc.src.spawn.posix_spawn_file_actions_init

# search.h entrypoints
libc.src.search.hcreate
libc.src.search.hcreate_r
libc.src.search.hsearch
libc.src.search.hsearch_r
libc.src.search.hdestroy
libc.src.search.hdestroy_r

# threads.h entrypoints
libc.src.threads.call_once
libc.src.threads.cnd_broadcast
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/x86_64/headers.txt
Expand Up @@ -17,6 +17,7 @@ set(TARGET_PUBLIC_HEADERS
libc.include.stdlib
libc.include.string
libc.include.strings
libc.include.search
libc.include.termios
libc.include.threads
libc.include.time
Expand Down
12 changes: 12 additions & 0 deletions libc/include/CMakeLists.txt
Expand Up @@ -133,6 +133,18 @@ add_gen_header(
.llvm-libc-types.size_t
)

add_gen_header(
search
DEF_FILE search.h.def
GEN_HDR search.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-types.ACTION
.llvm-libc-types.ENTRY
.llvm-libc-types.struct_hsearch_data
.llvm-libc-types.size_t
)

add_gen_header(
time
DEF_FILE time.h.def
Expand Down
14 changes: 14 additions & 0 deletions libc/include/llvm-libc-types/ACTION.h
@@ -0,0 +1,14 @@
//===-- Definition of ACTION type -----------------------------------------===//
//
// 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_TYPES_ACTION_H__
#define __LLVM_LIBC_TYPES_ACTION_H__

typedef enum { FIND, ENTER } ACTION;

#endif // __LLVM_LIBC_TYPES_ACTION_H__
3 changes: 3 additions & 0 deletions libc/include/llvm-libc-types/CMakeLists.txt
Expand Up @@ -91,3 +91,6 @@ add_header(wint_t HDR wint_t.h)
add_header(sa_family_t HDR sa_family_t.h)
add_header(struct_sockaddr HDR struct_sockaddr.h)
add_header(rpc_opcodes_t HDR rpc_opcodes_t.h)
add_header(ACTION HDR ACTION.h)
add_header(ENTRY HDR ENTRY.h)
add_header(struct_hsearch_data HDR struct_hsearch_data.h)
17 changes: 17 additions & 0 deletions libc/include/llvm-libc-types/ENTRY.h
@@ -0,0 +1,17 @@
//===-- Definition of ENTRY type ------------------------------------------===//
//
// 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_TYPES_ENTRY_H__
#define __LLVM_LIBC_TYPES_ENTRY_H__

typedef struct {
char *key;
void *data;
} ENTRY;

#endif // __LLVM_LIBC_TYPES_ENTRY_H__
17 changes: 17 additions & 0 deletions libc/include/llvm-libc-types/struct_hsearch_data.h
@@ -0,0 +1,17 @@
//===-- Definition of type struct hsearch_data ----------------------------===//
//
// 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_TYPES_STRUCT_HSEARCH_DATA_H__
#define __LLVM_LIBC_TYPES_STRUCT_HSEARCH_DATA_H__

struct hsearch_data {
void *__opaque;
unsigned int __unused[2];
};

#endif // __LLVM_LIBC_TYPES_STRUCT_HSEARCH_DATA_H__
18 changes: 18 additions & 0 deletions libc/include/search.h.def
@@ -0,0 +1,18 @@
//===-- POSIX header search.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_SEARCH_H
#define LLVM_LIBC_SEARCH_H

#include <__llvm-libc-common.h>
#define __need_size_t
#include <stddef.h>

%%public_api()

#endif // LLVM_LIBC_SEARCH_H
40 changes: 39 additions & 1 deletion libc/spec/gnu_ext.td
Expand Up @@ -3,6 +3,8 @@ def CpuSetPtr : PtrType<CpuSetT>;
def ConstCpuSetPtr : ConstType<CpuSetPtr>;

def QSortRCompareT : NamedType<"__qsortrcompare_t">;
def StructHsearchData : NamedType<"struct hsearch_data">;
def StructHsearchDataPtr : PtrType<StructHsearchData>;

def GnuExtensions : StandardSpec<"GNUExtensions"> {
NamedType CookieIOFunctionsT = NamedType<"cookie_io_functions_t">;
Expand Down Expand Up @@ -54,7 +56,6 @@ def GnuExtensions : StandardSpec<"GNUExtensions"> {
>,
]
>;

HeaderSpec String = HeaderSpec<
"string.h",
[], // Macros
Expand Down Expand Up @@ -89,6 +90,42 @@ def GnuExtensions : StandardSpec<"GNUExtensions"> {
]
>;

HeaderSpec Search = HeaderSpec<
"search.h",
[], // Macros
[
StructHsearchData
],
[], // Enumerations
[
FunctionSpec<
"hcreate_r",
RetValSpec<IntType>,
[
ArgSpec<SizeTType>,
ArgSpec<StructHsearchDataPtr>
]
>,
FunctionSpec<
"hdestroy_r",
RetValSpec<VoidType>,
[
ArgSpec<StructHsearchDataPtr>
]
>,
FunctionSpec<
"hsearch_r",
RetValSpec<IntType>,
[
ArgSpec<EntryType>,
ArgSpec<ActionType>,
ArgSpec<EntryTypePtrPtr>,
ArgSpec<StructHsearchDataPtr>
]
>,
]
>;

HeaderSpec FEnv = HeaderSpec<
"fenv.h",
[], // Macros
Expand Down Expand Up @@ -243,6 +280,7 @@ def GnuExtensions : StandardSpec<"GNUExtensions"> {
StdIO,
StdLib,
String,
Search,
UniStd,
];
}
35 changes: 34 additions & 1 deletion libc/spec/posix.td
Expand Up @@ -1269,6 +1269,38 @@ def POSIX : StandardSpec<"POSIX"> {
]
>;

HeaderSpec Search = HeaderSpec<
"search.h",
[], // Macros
[
ActionType,
EntryType
], // Types
[], // Enumerations
[
FunctionSpec<
"hcreate",
RetValSpec<IntType>,
[
ArgSpec<SizeTType>
]
>,
FunctionSpec<
"hdestroy",
RetValSpec<VoidType>,
[] // Args
>,
FunctionSpec<
"hsearch",
RetValSpec<EntryTypePtr>,
[
ArgSpec<EntryType>,
ArgSpec<ActionType>
]
>,
]
>;

HeaderSpec Termios = HeaderSpec<
"termios.h",
[
Expand Down Expand Up @@ -1414,6 +1446,7 @@ def POSIX : StandardSpec<"POSIX"> {
Time,
Termios,
UniStd,
String
String,
Search,
];
}
5 changes: 5 additions & 0 deletions libc/spec/spec.td
Expand Up @@ -140,6 +140,11 @@ def SuSecondsT : NamedType<"suseconds_t">;
//added because __assert_fail needs it.
def UnsignedType : NamedType<"unsigned">;

def ActionType : NamedType<"ACTION">;
def EntryType : NamedType<"ENTRY">;
def EntryTypePtr : PtrType<EntryType>;
def EntryTypePtrPtr : PtrType<EntryTypePtr>;

class Macro<string name> {
string Name = name;
}
Expand Down
1 change: 1 addition & 0 deletions libc/src/CMakeLists.txt
Expand Up @@ -35,3 +35,4 @@ add_subdirectory(signal)
add_subdirectory(spawn)
add_subdirectory(threads)
add_subdirectory(time)
add_subdirectory(search)

0 comments on commit 81e3e7e

Please sign in to comment.