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    COMPILE_OPTIONS
312      -fno-builtin-memcmp
313      -fno-builtin-bcmp
314    ${ARGN}
315  )
316endfunction()
317
318if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
319  add_bcmp(bcmp_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
320  add_bcmp(bcmp_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
321  add_bcmp(bcmp_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
322  add_bcmp(bcmp_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
323  add_bcmp(bcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
324  add_bcmp(bcmp)
325else()
326  add_bcmp(bcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
327  add_bcmp(bcmp)
328endif()
329
330# ------------------------------------------------------------------------------
331# bzero
332# ------------------------------------------------------------------------------
333
334function(add_bzero bzero_name)
335  add_implementation(bzero ${bzero_name}
336    SRCS ${LIBC_SOURCE_DIR}/src/string/bzero.cpp
337    HDRS ${LIBC_SOURCE_DIR}/src/string/bzero.h
338    DEPENDS
339      .memory_utils.memset_implementation
340      libc.include.string
341    COMPILE_OPTIONS
342      -fno-builtin-bzero
343    ${ARGN}
344  )
345endfunction()
346
347if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
348  add_bzero(bzero_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
349  add_bzero(bzero_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
350  add_bzero(bzero_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
351  add_bzero(bzero_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
352  add_bzero(bzero_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
353  add_bzero(bzero)
354else()
355  add_bzero(bzero_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
356  add_bzero(bzero)
357endif()
358
359# ------------------------------------------------------------------------------
360# memcmp
361# ------------------------------------------------------------------------------
362
363function(add_memcmp memcmp_name)
364  add_implementation(memcmp ${memcmp_name}
365    SRCS ${LIBC_SOURCE_DIR}/src/string/memcmp.cpp
366    HDRS ${LIBC_SOURCE_DIR}/src/string/memcmp.h
367    DEPENDS
368      .memory_utils.memcmp_implementation
369      libc.include.string
370    COMPILE_OPTIONS
371      -fno-builtin-memcmp
372    ${ARGN}
373  )
374endfunction()
375
376if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
377  add_memcmp(memcmp_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
378  add_memcmp(memcmp_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
379  add_memcmp(memcmp_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
380  add_memcmp(memcmp_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
381  add_memcmp(memcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
382  add_memcmp(memcmp)
383elseif(${LIBC_TARGET_ARCHITECTURE_IS_AARCH64})
384  add_memcmp(memcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
385  add_memcmp(memcmp)
386else()
387  add_memcmp(memcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
388  add_memcmp(memcmp)
389endif()
390
391# ------------------------------------------------------------------------------
392# memcpy
393# ------------------------------------------------------------------------------
394
395function(add_memcpy memcpy_name)
396  add_implementation(memcpy ${memcpy_name}
397    SRCS ${LIBC_SOURCE_DIR}/src/string/memcpy.cpp
398    HDRS ${LIBC_SOURCE_DIR}/src/string/memcpy.h
399    DEPENDS
400      .memory_utils.memcpy_implementation
401      libc.include.string
402    COMPILE_OPTIONS
403      -fno-builtin-memcpy
404    ${ARGN}
405  )
406endfunction()
407
408if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
409  add_memcpy(memcpy_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
410  add_memcpy(memcpy_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
411  add_memcpy(memcpy_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
412  add_memcpy(memcpy_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
413  add_memcpy(memcpy_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
414  add_memcpy(memcpy)
415elseif(${LIBC_TARGET_ARCHITECTURE_IS_AARCH64})
416  # Disable tail merging as it leads to lower performance.
417  add_memcpy(memcpy_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE}
418                                      MLLVM_COMPILE_OPTIONS "-tail-merge-threshold=0")
419  add_memcpy(memcpy                   MLLVM_COMPILE_OPTIONS "-tail-merge-threshold=0")
420else()
421  add_memcpy(memcpy_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
422  add_memcpy(memcpy)
423endif()
424
425# ------------------------------------------------------------------------------
426# memmove
427# ------------------------------------------------------------------------------
428
429function(add_memmove memmove_name)
430  add_implementation(memmove ${memmove_name}
431    SRCS ${LIBC_SOURCE_DIR}/src/string/memmove.cpp
432    HDRS ${LIBC_SOURCE_DIR}/src/string/memmove.h
433    DEPENDS
434      .memory_utils.memory_utils
435      libc.include.string
436    COMPILE_OPTIONS
437      -fno-builtin
438    ${ARGN}
439  )
440endfunction()
441
442if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
443  add_memmove(memmove_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
444  add_memmove(memmove_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
445  add_memmove(memmove_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
446  add_memmove(memmove_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
447  add_memmove(memmove_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
448  add_memmove(memmove)
449elseif(${LIBC_TARGET_ARCHITECTURE_IS_AARCH64})
450  # Disable tail merging as it leads to lower performance.
451  add_memmove(memmove_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE}
452                                        MLLVM_COMPILE_OPTIONS "-tail-merge-threshold=0")
453  add_memmove(memmove                   MLLVM_COMPILE_OPTIONS "-tail-merge-threshold=0")
454else()
455  add_memmove(memmove_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
456  add_memmove(memmove)
457endif()
458
459# ------------------------------------------------------------------------------
460# memset
461# ------------------------------------------------------------------------------
462
463function(add_memset memset_name)
464  add_implementation(memset ${memset_name}
465    SRCS ${LIBC_SOURCE_DIR}/src/string/memset.cpp
466    HDRS ${LIBC_SOURCE_DIR}/src/string/memset.h
467    DEPENDS
468      .memory_utils.memset_implementation
469      libc.include.string
470    COMPILE_OPTIONS
471      -fno-builtin-memset
472    ${ARGN}
473  )
474endfunction()
475
476if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
477  add_memset(memset_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
478  add_memset(memset_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
479  add_memset(memset_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
480  add_memset(memset_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
481  add_memset(memset_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
482  add_memset(memset)
483elseif(${LIBC_TARGET_ARCHITECTURE_IS_AARCH64})
484  # Disable tail merging as it leads to lower performance.
485  add_memset(memset_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE}
486                                      MLLVM_COMPILE_OPTIONS "-tail-merge-threshold=0")
487  add_memset(memset                   MLLVM_COMPILE_OPTIONS "-tail-merge-threshold=0")
488else()
489  add_memset(memset_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
490  add_memset(memset)
491endif()
492