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