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    list(APPEND ADD_IMPL_MLLVM_COMPILE_OPTIONS "-combiner-global-alias-analysis")
283    # Note that '-mllvm' needs to be prefixed with 'SHELL:' to prevent CMake flag deduplication.
284    foreach(opt IN LISTS ADD_IMPL_MLLVM_COMPILE_OPTIONS)
285      list(APPEND ADD_IMPL_COMPILE_OPTIONS "SHELL:-mllvm ${opt}")
286    endforeach()
287  endif()
288
289  add_entrypoint_object(${impl_name}
290    NAME ${name}
291    SRCS ${ADD_IMPL_SRCS}
292    HDRS ${ADD_IMPL_HDRS}
293    DEPENDS ${ADD_IMPL_DEPENDS}
294    COMPILE_OPTIONS ${ADD_IMPL_COMPILE_OPTIONS}
295  )
296  get_fq_target_name(${impl_name} fq_target_name)
297  set_target_properties(${fq_target_name} PROPERTIES REQUIRE_CPU_FEATURES "${ADD_IMPL_REQUIRE}")
298  set_property(GLOBAL APPEND PROPERTY "${name}_implementations" "${fq_target_name}")
299endfunction()
300
301# ------------------------------------------------------------------------------
302# bcmp
303# ------------------------------------------------------------------------------
304
305function(add_bcmp bcmp_name)
306  add_implementation(bcmp ${bcmp_name}
307    SRCS ${LIBC_SOURCE_DIR}/src/string/bcmp.cpp
308    HDRS ${LIBC_SOURCE_DIR}/src/string/bcmp.h
309    DEPENDS
310      .memory_utils.memory_utils
311      libc.include.string
312    COMPILE_OPTIONS
313      -fno-builtin-memcmp
314      -fno-builtin-bcmp
315    ${ARGN}
316  )
317endfunction()
318
319if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
320  add_bcmp(bcmp_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
321  add_bcmp(bcmp_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
322  add_bcmp(bcmp_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
323  add_bcmp(bcmp_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
324  add_bcmp(bcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
325  add_bcmp(bcmp)
326else()
327  add_bcmp(bcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
328  add_bcmp(bcmp)
329endif()
330
331# ------------------------------------------------------------------------------
332# bzero
333# ------------------------------------------------------------------------------
334
335function(add_bzero bzero_name)
336  add_implementation(bzero ${bzero_name}
337    SRCS ${LIBC_SOURCE_DIR}/src/string/bzero.cpp
338    HDRS ${LIBC_SOURCE_DIR}/src/string/bzero.h
339    DEPENDS
340      .memory_utils.memset_implementation
341      libc.include.string
342    COMPILE_OPTIONS
343      -fno-builtin-bzero
344    ${ARGN}
345  )
346endfunction()
347
348if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
349  add_bzero(bzero_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
350  add_bzero(bzero_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
351  add_bzero(bzero_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
352  add_bzero(bzero_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
353  add_bzero(bzero_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
354  add_bzero(bzero)
355else()
356  add_bzero(bzero_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
357  add_bzero(bzero)
358endif()
359
360# ------------------------------------------------------------------------------
361# memcmp
362# ------------------------------------------------------------------------------
363
364function(add_memcmp memcmp_name)
365  add_implementation(memcmp ${memcmp_name}
366    SRCS ${LIBC_SOURCE_DIR}/src/string/memcmp.cpp
367    HDRS ${LIBC_SOURCE_DIR}/src/string/memcmp.h
368    DEPENDS
369      .memory_utils.memcmp_implementation
370      libc.include.string
371    COMPILE_OPTIONS
372      -fno-builtin-memcmp
373    ${ARGN}
374  )
375endfunction()
376
377if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
378  add_memcmp(memcmp_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
379  add_memcmp(memcmp_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
380  add_memcmp(memcmp_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
381  add_memcmp(memcmp_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
382  add_memcmp(memcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
383  add_memcmp(memcmp)
384elseif(${LIBC_TARGET_ARCHITECTURE_IS_AARCH64})
385  add_memcmp(memcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
386  add_memcmp(memcmp)
387else()
388  add_memcmp(memcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
389  add_memcmp(memcmp)
390endif()
391
392# ------------------------------------------------------------------------------
393# memcpy
394# ------------------------------------------------------------------------------
395
396function(add_memcpy memcpy_name)
397  add_implementation(memcpy ${memcpy_name}
398    SRCS ${LIBC_SOURCE_DIR}/src/string/memcpy.cpp
399    HDRS ${LIBC_SOURCE_DIR}/src/string/memcpy.h
400    DEPENDS
401      .memory_utils.memcpy_implementation
402      libc.include.string
403    COMPILE_OPTIONS
404      -fno-builtin-memcpy
405    ${ARGN}
406  )
407endfunction()
408
409if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
410  add_memcpy(memcpy_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
411  add_memcpy(memcpy_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
412  add_memcpy(memcpy_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
413  add_memcpy(memcpy_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
414  add_memcpy(memcpy_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
415  add_memcpy(memcpy)
416elseif(${LIBC_TARGET_ARCHITECTURE_IS_AARCH64})
417  # Disable tail merging as it leads to lower performance.
418  add_memcpy(memcpy_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE}
419                                      MLLVM_COMPILE_OPTIONS "-tail-merge-threshold=0")
420  add_memcpy(memcpy                   MLLVM_COMPILE_OPTIONS "-tail-merge-threshold=0")
421else()
422  add_memcpy(memcpy_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
423  add_memcpy(memcpy)
424endif()
425
426# ------------------------------------------------------------------------------
427# memmove
428# ------------------------------------------------------------------------------
429
430function(add_memmove memmove_name)
431  add_implementation(memmove ${memmove_name}
432    SRCS ${LIBC_SOURCE_DIR}/src/string/memmove.cpp
433    HDRS ${LIBC_SOURCE_DIR}/src/string/memmove.h
434    DEPENDS
435      .memory_utils.memory_utils
436      libc.include.string
437    COMPILE_OPTIONS
438      -fno-builtin
439    ${ARGN}
440  )
441endfunction()
442
443if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
444  add_memmove(memmove_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
445  add_memmove(memmove_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
446  add_memmove(memmove_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
447  add_memmove(memmove_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
448  add_memmove(memmove_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
449  add_memmove(memmove)
450elseif(${LIBC_TARGET_ARCHITECTURE_IS_AARCH64})
451  # Disable tail merging as it leads to lower performance.
452  add_memmove(memmove_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE}
453                                        MLLVM_COMPILE_OPTIONS "-tail-merge-threshold=0")
454  add_memmove(memmove                   MLLVM_COMPILE_OPTIONS "-tail-merge-threshold=0")
455else()
456  add_memmove(memmove_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
457  add_memmove(memmove)
458endif()
459
460# ------------------------------------------------------------------------------
461# memset
462# ------------------------------------------------------------------------------
463
464function(add_memset memset_name)
465  add_implementation(memset ${memset_name}
466    SRCS ${LIBC_SOURCE_DIR}/src/string/memset.cpp
467    HDRS ${LIBC_SOURCE_DIR}/src/string/memset.h
468    DEPENDS
469      .memory_utils.memset_implementation
470      libc.include.string
471    COMPILE_OPTIONS
472      -fno-builtin-memset
473    ${ARGN}
474  )
475endfunction()
476
477if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
478  add_memset(memset_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
479  add_memset(memset_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
480  add_memset(memset_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
481  add_memset(memset_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
482  add_memset(memset_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
483  add_memset(memset)
484elseif(${LIBC_TARGET_ARCHITECTURE_IS_AARCH64})
485  # Disable tail merging as it leads to lower performance.
486  add_memset(memset_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE}
487                                      MLLVM_COMPILE_OPTIONS "-tail-merge-threshold=0")
488  add_memset(memset                   MLLVM_COMPILE_OPTIONS "-tail-merge-threshold=0")
489else()
490  add_memset(memset_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
491  add_memset(memset)
492endif()
493