1add_subdirectory(memory_utils)
2
3add_header_library(
4  string_utils
5  HDRS
6    string_utils.h
7  DEPENDS
8    libc.src.__support.CPP.bitset
9    .memory_utils.memcpy_implementation
10    .memory_utils.memset_implementation
11)
12
13add_entrypoint_object(
14  memccpy
15  SRCS
16    memccpy.cpp
17  HDRS
18    memccpy.h
19)
20
21
22add_entrypoint_object(
23  mempcpy
24  SRCS
25    mempcpy.cpp
26  HDRS
27    mempcpy.h
28  DEPENDS
29    .memory_utils.memcpy_implementation
30)
31
32add_entrypoint_object(
33  memchr
34  SRCS
35    memchr.cpp
36  HDRS
37    memchr.h
38  DEPENDS
39    .string_utils
40)
41
42add_entrypoint_object(
43  memrchr
44  SRCS
45    memrchr.cpp
46  HDRS
47    memrchr.h
48)
49
50add_entrypoint_object(
51  stpcpy
52  SRCS
53    stpcpy.cpp
54  HDRS
55    stpcpy.h
56  DEPENDS
57    .mempcpy
58    .string_utils
59)
60
61add_entrypoint_object(
62  stpncpy
63  SRCS
64    stpncpy.cpp
65  HDRS
66    stpncpy.h
67  DEPENDS
68    .memory_utils.memset_implementation
69)
70
71add_entrypoint_object(
72  strcat
73  SRCS
74    strcat.cpp
75  HDRS
76    strcat.h
77  DEPENDS
78    .strcpy
79    .string_utils
80)
81
82add_entrypoint_object(
83  strchr
84  SRCS
85    strchr.cpp
86  HDRS
87    strchr.h
88)
89
90add_entrypoint_object(
91  strcmp
92  SRCS
93    strcmp.cpp
94  HDRS
95    strcmp.h
96)
97
98add_entrypoint_object(
99  strcpy
100  SRCS
101    strcpy.cpp
102  HDRS
103    strcpy.h
104  DEPENDS
105    .memory_utils.memcpy_implementation
106    .string_utils
107)
108
109add_entrypoint_object(
110  strcspn
111  SRCS
112    strcspn.cpp
113  HDRS
114    strcspn.h
115  DEPENDS
116    .string_utils
117)
118
119add_entrypoint_object(
120  strdup
121  SRCS
122    strdup.cpp
123  HDRS
124    strdup.h
125  DEPENDS
126    .memory_utils.memcpy_implementation
127    .string_utils
128    libc.include.stdlib
129)
130
131add_entrypoint_object(
132  strlcat
133  SRCS
134    strlcat.cpp
135  HDRS
136    strlcat.h
137  DEPENDS
138    .string_utils
139    libc.include.string
140)
141
142add_entrypoint_object(
143  strlcpy
144  SRCS
145    strlcpy.cpp
146  HDRS
147    strlcpy.h
148  DEPENDS
149    .string_utils
150    libc.include.string
151)
152
153add_entrypoint_object(
154  strlen
155  SRCS
156    strlen.cpp
157  HDRS
158    strlen.h
159  DEPENDS
160    libc.include.string
161)
162
163add_entrypoint_object(
164  strncat
165  SRCS
166    strncat.cpp
167  HDRS
168    strncat.h
169  DEPENDS
170    .strncpy
171    .string_utils
172)
173
174add_entrypoint_object(
175  strncmp
176  SRCS
177    strncmp.cpp
178  HDRS
179    strncmp.h
180)
181
182add_entrypoint_object(
183  strncpy
184  SRCS
185    strncpy.cpp
186  HDRS
187    strncpy.h
188)
189
190add_entrypoint_object(
191  strndup
192  SRCS
193    strndup.cpp
194  HDRS
195    strndup.h
196  DEPENDS
197    .memory_utils.memcpy_implementation
198    .string_utils
199    libc.include.stdlib
200)
201
202add_entrypoint_object(
203  strnlen
204  SRCS
205    strnlen.cpp
206  HDRS
207    strnlen.h
208  DEPENDS
209    .string_utils
210)
211
212add_entrypoint_object(
213  strpbrk
214  SRCS
215    strpbrk.cpp
216  HDRS
217    strpbrk.h
218  DEPENDS
219    .string_utils
220)
221
222add_entrypoint_object(
223  strrchr
224  SRCS
225    strrchr.cpp
226  HDRS
227    strrchr.h
228)
229
230add_entrypoint_object(
231  strspn
232  SRCS
233    strspn.cpp
234  HDRS
235    strspn.h
236  DEPENDS
237    libc.src.__support.CPP.bitset
238)
239
240add_entrypoint_object(
241  strstr
242  SRCS
243    strstr.cpp
244  HDRS
245    strstr.h
246)
247
248add_entrypoint_object(
249  strtok
250  SRCS
251    strtok.cpp
252  HDRS
253    strtok.h
254  DEPENDS
255    .string_utils
256)
257
258add_entrypoint_object(
259  strtok_r
260  SRCS
261    strtok_r.cpp
262  HDRS
263    strtok_r.h
264  DEPENDS
265    .string_utils
266)
267
268# Helper to define a function with multiple implementations
269# - Computes flags to satisfy required/rejected features and arch,
270# - Declares an entry point,
271# - Attach the REQUIRE_CPU_FEATURES property to the target,
272# - Add the fully qualified target to `${name}_implementations` global property for tests.
273function(add_implementation name impl_name)
274  cmake_parse_arguments(
275    "ADD_IMPL"
276    "" # Optional arguments
277    "" # Single value arguments
278    "REQUIRE;SRCS;HDRS;DEPENDS;COMPILE_OPTIONS;MLLVM_COMPILE_OPTIONS" # Multi value arguments
279    ${ARGN})
280
281  if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
282    # Note that '-mllvm' needs to be prefixed with 'SHELL:' to prevent CMake flag deduplication.
283    foreach(opt IN LISTS ADD_IMPL_MLLVM_COMPILE_OPTIONS)
284      list(APPEND ADD_IMPL_COMPILE_OPTIONS "SHELL:-mllvm ${opt}")
285    endforeach()
286  endif()
287
288  add_entrypoint_object(${impl_name}
289    NAME ${name}
290    SRCS ${ADD_IMPL_SRCS}
291    HDRS ${ADD_IMPL_HDRS}
292    DEPENDS ${ADD_IMPL_DEPENDS}
293    COMPILE_OPTIONS ${ADD_IMPL_COMPILE_OPTIONS}
294  )
295  get_fq_target_name(${impl_name} fq_target_name)
296  set_target_properties(${fq_target_name} PROPERTIES REQUIRE_CPU_FEATURES "${ADD_IMPL_REQUIRE}")
297  set_property(GLOBAL APPEND PROPERTY "${name}_implementations" "${fq_target_name}")
298endfunction()
299
300# ------------------------------------------------------------------------------
301# bcmp
302# ------------------------------------------------------------------------------
303
304function(add_bcmp bcmp_name)
305  add_implementation(bcmp ${bcmp_name}
306    SRCS ${LIBC_SOURCE_DIR}/src/string/bcmp.cpp
307    HDRS ${LIBC_SOURCE_DIR}/src/string/bcmp.h
308    DEPENDS
309      .memory_utils.memory_utils
310      libc.include.string
311    ${ARGN}
312  )
313endfunction()
314
315if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
316  add_bcmp(bcmp_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
317  add_bcmp(bcmp_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
318  add_bcmp(bcmp_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
319  add_bcmp(bcmp_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
320  add_bcmp(bcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
321  add_bcmp(bcmp)
322else()
323  add_bcmp(bcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
324  add_bcmp(bcmp)
325endif()
326
327# ------------------------------------------------------------------------------
328# bzero
329# ------------------------------------------------------------------------------
330
331function(add_bzero bzero_name)
332  add_implementation(bzero ${bzero_name}
333    SRCS ${LIBC_SOURCE_DIR}/src/string/bzero.cpp
334    HDRS ${LIBC_SOURCE_DIR}/src/string/bzero.h
335    DEPENDS
336      .memory_utils.memset_implementation
337      libc.include.string
338    ${ARGN}
339  )
340endfunction()
341
342if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
343  add_bzero(bzero_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
344  add_bzero(bzero_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
345  add_bzero(bzero_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
346  add_bzero(bzero_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
347  add_bzero(bzero_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
348  add_bzero(bzero)
349else()
350  add_bzero(bzero_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
351  add_bzero(bzero)
352endif()
353
354# ------------------------------------------------------------------------------
355# memcmp
356# ------------------------------------------------------------------------------
357
358function(add_memcmp memcmp_name)
359  add_implementation(memcmp ${memcmp_name}
360    SRCS ${LIBC_SOURCE_DIR}/src/string/memcmp.cpp
361    HDRS ${LIBC_SOURCE_DIR}/src/string/memcmp.h
362    DEPENDS
363      .memory_utils.memcmp_implementation
364      libc.include.string
365    ${ARGN}
366  )
367endfunction()
368
369if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
370  add_memcmp(memcmp_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
371  add_memcmp(memcmp_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
372  add_memcmp(memcmp_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
373  add_memcmp(memcmp_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
374  add_memcmp(memcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
375  add_memcmp(memcmp)
376elseif(${LIBC_TARGET_ARCHITECTURE_IS_AARCH64})
377  add_memcmp(memcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
378  add_memcmp(memcmp)
379else()
380  add_memcmp(memcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
381  add_memcmp(memcmp)
382endif()
383
384# ------------------------------------------------------------------------------
385# memcpy
386# ------------------------------------------------------------------------------
387
388function(add_memcpy memcpy_name)
389  add_implementation(memcpy ${memcpy_name}
390    SRCS ${LIBC_SOURCE_DIR}/src/string/memcpy.cpp
391    HDRS ${LIBC_SOURCE_DIR}/src/string/memcpy.h
392    DEPENDS
393      .memory_utils.memcpy_implementation
394      libc.include.string
395    ${ARGN}
396  )
397endfunction()
398
399if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
400  add_memcpy(memcpy_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
401  add_memcpy(memcpy_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
402  add_memcpy(memcpy_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
403  add_memcpy(memcpy_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
404  add_memcpy(memcpy_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
405  add_memcpy(memcpy)
406elseif(${LIBC_TARGET_ARCHITECTURE_IS_AARCH64})
407  # Disable tail merging as it leads to lower performance.
408  add_memcpy(memcpy_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE}
409                                      MLLVM_COMPILE_OPTIONS "-tail-merge-threshold=0")
410  add_memcpy(memcpy                   MLLVM_COMPILE_OPTIONS "-tail-merge-threshold=0")
411else()
412  add_memcpy(memcpy_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
413  add_memcpy(memcpy)
414endif()
415
416# ------------------------------------------------------------------------------
417# memmove
418# ------------------------------------------------------------------------------
419
420function(add_memmove memmove_name)
421  add_implementation(memmove ${memmove_name}
422    SRCS ${LIBC_SOURCE_DIR}/src/string/memmove.cpp
423    HDRS ${LIBC_SOURCE_DIR}/src/string/memmove.h
424    DEPENDS
425      .memory_utils.memory_utils
426      libc.include.string
427    ${ARGN}
428  )
429endfunction()
430
431if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
432  add_memmove(memmove_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
433  add_memmove(memmove_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
434  add_memmove(memmove_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
435  add_memmove(memmove_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
436  add_memmove(memmove_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
437  add_memmove(memmove)
438elseif(${LIBC_TARGET_ARCHITECTURE_IS_AARCH64})
439  # Disable tail merging as it leads to lower performance.
440  add_memmove(memmove_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE}
441                                        MLLVM_COMPILE_OPTIONS "-tail-merge-threshold=0")
442  add_memmove(memmove                   MLLVM_COMPILE_OPTIONS "-tail-merge-threshold=0")
443else()
444  add_memmove(memmove_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
445  add_memmove(memmove)
446endif()
447
448# ------------------------------------------------------------------------------
449# memset
450# ------------------------------------------------------------------------------
451
452function(add_memset memset_name)
453  add_implementation(memset ${memset_name}
454    SRCS ${LIBC_SOURCE_DIR}/src/string/memset.cpp
455    HDRS ${LIBC_SOURCE_DIR}/src/string/memset.h
456    DEPENDS
457      .memory_utils.memset_implementation
458      libc.include.string
459    ${ARGN}
460  )
461endfunction()
462
463if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
464  add_memset(memset_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
465  add_memset(memset_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
466  add_memset(memset_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
467  add_memset(memset_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
468  add_memset(memset_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
469  add_memset(memset)
470elseif(${LIBC_TARGET_ARCHITECTURE_IS_AARCH64})
471  # Disable tail merging as it leads to lower performance.
472  add_memset(memset_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE}
473                                      MLLVM_COMPILE_OPTIONS "-tail-merge-threshold=0")
474  add_memset(memset                   MLLVM_COMPILE_OPTIONS "-tail-merge-threshold=0")
475else()
476  add_memset(memset_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
477  add_memset(memset)
478endif()
479