1add_subdirectory(memory_utils)
2
3add_header_library(
4  string_utils
5  HDRS
6    string_utils.h
7  DEPENDS
8    libc.utils.CPP.standalone_cpp
9)
10
11add_entrypoint_object(
12  strcat
13  SRCS
14    strcat.cpp
15  HDRS
16    strcat.h
17  DEPENDS
18    .strcpy
19    .string_utils
20)
21
22add_entrypoint_object(
23  strcpy
24  SRCS
25    strcpy.cpp
26  HDRS
27    strcpy.h
28  DEPENDS
29    .memcpy
30    .string_utils
31)
32
33add_entrypoint_object(
34  strlen
35  SRCS
36    strlen.cpp
37  HDRS
38    strlen.h
39  DEPENDS
40    libc.include.string
41)
42
43add_entrypoint_object(
44  strcmp
45  SRCS
46    strcmp.cpp
47  HDRS
48    strcmp.h
49)
50
51add_entrypoint_object(
52  strncmp
53  SRCS
54    strncmp.cpp
55  HDRS
56    strncmp.h
57)
58
59add_entrypoint_object(
60  memchr
61  SRCS
62    memchr.cpp
63  HDRS
64    memchr.h
65  DEPENDS
66    .string_utils
67)
68
69add_entrypoint_object(
70  memmove
71  SRCS
72    memmove.cpp
73  HDRS
74    memmove.h
75  DEPENDS
76    libc.src.__support.integer_operations
77    libc.src.string.memcpy
78)
79
80add_entrypoint_object(
81  strchr
82  SRCS
83    strchr.cpp
84  HDRS
85    strchr.h
86)
87
88add_entrypoint_object(
89  strstr
90  SRCS
91    strstr.cpp
92  HDRS
93    strstr.h
94)
95
96add_entrypoint_object(
97  strncpy
98  SRCS
99    strncpy.cpp
100  HDRS
101    strncpy.h
102)
103
104add_entrypoint_object(
105  strnlen
106  SRCS
107    strnlen.cpp
108  HDRS
109    strnlen.h
110  DEPENDS
111    .string_utils
112)
113
114add_entrypoint_object(
115  memrchr
116  SRCS
117    memrchr.cpp
118  HDRS
119    memrchr.h
120)
121
122add_entrypoint_object(
123  strrchr
124  SRCS
125    strrchr.cpp
126  HDRS
127    strrchr.h
128)
129
130add_entrypoint_object(
131  strcspn
132  SRCS
133    strcspn.cpp
134  HDRS
135    strcspn.h
136  DEPENDS
137    .string_utils
138)
139
140add_entrypoint_object(
141  strspn
142  SRCS
143    strspn.cpp
144  HDRS
145    strspn.h
146  DEPENDS
147    libc.utils.CPP.standalone_cpp
148)
149
150add_entrypoint_object(
151  strpbrk
152  SRCS
153    strpbrk.cpp
154  HDRS
155    strpbrk.h
156  DEPENDS
157    .string_utils
158)
159
160add_entrypoint_object(
161  strtok
162  SRCS
163    strtok.cpp
164  HDRS
165    strtok.h
166  DEPENDS
167    .string_utils
168)
169
170add_entrypoint_object(
171  strtok_r
172  SRCS
173    strtok_r.cpp
174  HDRS
175    strtok_r.h
176  DEPENDS
177    .string_utils
178)
179
180# Helper to define a function with multiple implementations
181# - Computes flags to satisfy required/rejected features and arch,
182# - Declares an entry point,
183# - Attach the REQUIRE_CPU_FEATURES property to the target,
184# - Add the fully qualified target to `${name}_implementations` global property for tests.
185function(add_implementation name impl_name)
186  cmake_parse_arguments(
187    "ADD_IMPL"
188    "" # Optional arguments
189    "" # Single value arguments
190    "REQUIRE;SRCS;HDRS;DEPENDS;COMPILE_OPTIONS" # Multi value arguments
191    ${ARGN})
192  add_entrypoint_object(${impl_name}
193    NAME ${name}
194    SRCS ${ADD_IMPL_SRCS}
195    HDRS ${ADD_IMPL_HDRS}
196    DEPENDS ${ADD_IMPL_DEPENDS}
197    COMPILE_OPTIONS ${ADD_IMPL_COMPILE_OPTIONS} "SHELL:-mllvm -combiner-global-alias-analysis"
198  )
199  get_fq_target_name(${impl_name} fq_target_name)
200  set_target_properties(${fq_target_name} PROPERTIES REQUIRE_CPU_FEATURES "${ADD_IMPL_REQUIRE}")
201  set_property(GLOBAL APPEND PROPERTY "${name}_implementations" "${fq_target_name}")
202endfunction()
203
204# ------------------------------------------------------------------------------
205# memcpy
206# ------------------------------------------------------------------------------
207
208function(add_memcpy memcpy_name)
209  add_implementation(memcpy ${memcpy_name}
210    SRCS ${MEMCPY_SRC}
211    HDRS ${LIBC_SOURCE_DIR}/src/string/memcpy.h
212    DEPENDS
213      .memory_utils.memory_utils
214      libc.include.string
215    COMPILE_OPTIONS
216      -fno-builtin-memcpy
217    ${ARGN}
218  )
219endfunction()
220
221if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
222  set(MEMCPY_SRC ${LIBC_SOURCE_DIR}/src/string/x86_64/memcpy.cpp)
223  add_memcpy(memcpy_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
224  add_memcpy(memcpy_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
225  add_memcpy(memcpy_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
226  add_memcpy(memcpy_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
227  add_memcpy(memcpy_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
228  add_memcpy(memcpy)
229elseif(${LIBC_TARGET_ARCHITECTURE_IS_AARCH64})
230  set(MEMCPY_SRC ${LIBC_SOURCE_DIR}/src/string/aarch64/memcpy.cpp)
231  # Disable tail merging as it leads to lower performance.
232  # Note that '-mllvm' needs to be prefixed with 'SHELL:' to prevent CMake flag deduplication.
233  add_memcpy(memcpy_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE}
234                                      COMPILE_OPTIONS "SHELL:-mllvm --tail-merge-threshold=0")
235  add_memcpy(memcpy                   COMPILE_OPTIONS "SHELL:-mllvm --tail-merge-threshold=0")
236else()
237  set(MEMCPY_SRC ${LIBC_SOURCE_DIR}/src/string/memcpy.cpp)
238  add_memcpy(memcpy_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
239  add_memcpy(memcpy)
240endif()
241
242# ------------------------------------------------------------------------------
243# memset
244# ------------------------------------------------------------------------------
245
246function(add_memset memset_name)
247  add_implementation(memset ${memset_name}
248    SRCS ${LIBC_SOURCE_DIR}/src/string/memset.cpp
249    HDRS ${LIBC_SOURCE_DIR}/src/string/memset.h
250    DEPENDS
251      .memory_utils.memory_utils
252      libc.include.string
253    COMPILE_OPTIONS
254      -fno-builtin-memset
255    ${ARGN}
256  )
257endfunction()
258
259if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
260  add_memset(memset_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
261  add_memset(memset_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
262  add_memset(memset_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
263  add_memset(memset_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
264  add_memset(memset_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
265  add_memset(memset)
266else()
267  add_memset(memset_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
268  add_memset(memset)
269endif()
270
271# ------------------------------------------------------------------------------
272# bzero
273# ------------------------------------------------------------------------------
274
275function(add_bzero bzero_name)
276  add_implementation(bzero ${bzero_name}
277    SRCS ${LIBC_SOURCE_DIR}/src/string/bzero.cpp
278    HDRS ${LIBC_SOURCE_DIR}/src/string/bzero.h
279    DEPENDS
280      .memory_utils.memory_utils
281      libc.include.string
282    COMPILE_OPTIONS
283      -fno-builtin-bzero
284    ${ARGN}
285  )
286endfunction()
287
288if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
289  add_bzero(bzero_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
290  add_bzero(bzero_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
291  add_bzero(bzero_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
292  add_bzero(bzero_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
293  add_bzero(bzero_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
294  add_bzero(bzero)
295else()
296  add_bzero(bzero_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
297  add_bzero(bzero)
298endif()
299
300# ------------------------------------------------------------------------------
301# memcmp
302# ------------------------------------------------------------------------------
303
304function(add_memcmp memcmp_name)
305  add_implementation(memcmp ${memcmp_name}
306    SRCS ${LIBC_MEMCMP_SRC}
307    HDRS ${LIBC_SOURCE_DIR}/src/string/memcmp.h
308    DEPENDS
309      .memory_utils.memory_utils
310      libc.include.string
311    COMPILE_OPTIONS
312      -fno-builtin-memcmp
313    ${ARGN}
314  )
315endfunction()
316
317if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
318  set(LIBC_MEMCMP_SRC ${LIBC_SOURCE_DIR}/src/string/memcmp.cpp)
319  add_memcmp(memcmp_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
320  add_memcmp(memcmp_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
321  add_memcmp(memcmp_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
322  add_memcmp(memcmp_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
323  add_memcmp(memcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
324  add_memcmp(memcmp)
325elseif(${LIBC_TARGET_ARCHITECTURE_IS_AARCH64})
326  set(LIBC_MEMCMP_SRC ${LIBC_SOURCE_DIR}/src/string/aarch64/memcmp.cpp)
327  add_memcmp(memcmp)
328  add_memcmp(memcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
329else()
330  set(LIBC_MEMCMP_SRC ${LIBC_SOURCE_DIR}/src/string/memcmp.cpp)
331  add_memcmp(memcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
332  add_memcmp(memcmp)
333endif()
334