1add_subdirectory(memory_utils)
2
3add_header_library(
4  string_utils
5  HDRS
6    string_utils.h
7  DEPENDS
8    libc.src.__support.CPP.standalone_cpp
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  strlen
131  SRCS
132    strlen.cpp
133  HDRS
134    strlen.h
135  DEPENDS
136    libc.include.string
137)
138
139add_entrypoint_object(
140  strncat
141  SRCS
142    strncat.cpp
143  HDRS
144    strncat.h
145  DEPENDS
146    .strncpy
147    .string_utils
148)
149
150add_entrypoint_object(
151  strncmp
152  SRCS
153    strncmp.cpp
154  HDRS
155    strncmp.h
156)
157
158add_entrypoint_object(
159  strncpy
160  SRCS
161    strncpy.cpp
162  HDRS
163    strncpy.h
164)
165
166add_entrypoint_object(
167  strndup
168  SRCS
169    strndup.cpp
170  HDRS
171    strndup.h
172  DEPENDS
173    .memory_utils.memcpy_implementation
174    .string_utils
175    libc.include.stdlib
176)
177
178add_entrypoint_object(
179  strnlen
180  SRCS
181    strnlen.cpp
182  HDRS
183    strnlen.h
184  DEPENDS
185    .string_utils
186)
187
188add_entrypoint_object(
189  strpbrk
190  SRCS
191    strpbrk.cpp
192  HDRS
193    strpbrk.h
194  DEPENDS
195    .string_utils
196)
197
198add_entrypoint_object(
199  strrchr
200  SRCS
201    strrchr.cpp
202  HDRS
203    strrchr.h
204)
205
206add_entrypoint_object(
207  strspn
208  SRCS
209    strspn.cpp
210  HDRS
211    strspn.h
212  DEPENDS
213    libc.src.__support.CPP.standalone_cpp
214)
215
216add_entrypoint_object(
217  strstr
218  SRCS
219    strstr.cpp
220  HDRS
221    strstr.h
222)
223
224add_entrypoint_object(
225  strtok
226  SRCS
227    strtok.cpp
228  HDRS
229    strtok.h
230  DEPENDS
231    .string_utils
232)
233
234add_entrypoint_object(
235  strtok_r
236  SRCS
237    strtok_r.cpp
238  HDRS
239    strtok_r.h
240  DEPENDS
241    .string_utils
242)
243
244# Helper to define a function with multiple implementations
245# - Computes flags to satisfy required/rejected features and arch,
246# - Declares an entry point,
247# - Attach the REQUIRE_CPU_FEATURES property to the target,
248# - Add the fully qualified target to `${name}_implementations` global property for tests.
249function(add_implementation name impl_name)
250  cmake_parse_arguments(
251    "ADD_IMPL"
252    "" # Optional arguments
253    "" # Single value arguments
254    "REQUIRE;SRCS;HDRS;DEPENDS;COMPILE_OPTIONS" # Multi value arguments
255    ${ARGN})
256  add_entrypoint_object(${impl_name}
257    NAME ${name}
258    SRCS ${ADD_IMPL_SRCS}
259    HDRS ${ADD_IMPL_HDRS}
260    DEPENDS ${ADD_IMPL_DEPENDS}
261    COMPILE_OPTIONS ${ADD_IMPL_COMPILE_OPTIONS} "SHELL:-mllvm -combiner-global-alias-analysis"
262  )
263  get_fq_target_name(${impl_name} fq_target_name)
264  set_target_properties(${fq_target_name} PROPERTIES REQUIRE_CPU_FEATURES "${ADD_IMPL_REQUIRE}")
265  set_property(GLOBAL APPEND PROPERTY "${name}_implementations" "${fq_target_name}")
266endfunction()
267
268# ------------------------------------------------------------------------------
269# bcmp
270# ------------------------------------------------------------------------------
271
272function(add_bcmp bcmp_name)
273  add_implementation(bcmp ${bcmp_name}
274    SRCS ${LIBC_SOURCE_DIR}/src/string/bcmp.cpp
275    HDRS ${LIBC_SOURCE_DIR}/src/string/bcmp.h
276    DEPENDS
277      .memory_utils.memory_utils
278      libc.include.string
279    COMPILE_OPTIONS
280      -fno-builtin-memcmp
281      -fno-builtin-bcmp
282    ${ARGN}
283  )
284endfunction()
285
286if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
287  add_bcmp(bcmp_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
288  add_bcmp(bcmp_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
289  add_bcmp(bcmp_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
290  add_bcmp(bcmp_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
291  add_bcmp(bcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
292  add_bcmp(bcmp)
293else()
294  add_bcmp(bcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
295  add_bcmp(bcmp)
296endif()
297
298# ------------------------------------------------------------------------------
299# bzero
300# ------------------------------------------------------------------------------
301
302function(add_bzero bzero_name)
303  add_implementation(bzero ${bzero_name}
304    SRCS ${LIBC_SOURCE_DIR}/src/string/bzero.cpp
305    HDRS ${LIBC_SOURCE_DIR}/src/string/bzero.h
306    DEPENDS
307      .memory_utils.memset_implementation
308      libc.include.string
309    COMPILE_OPTIONS
310      -fno-builtin-bzero
311    ${ARGN}
312  )
313endfunction()
314
315if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
316  add_bzero(bzero_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
317  add_bzero(bzero_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
318  add_bzero(bzero_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
319  add_bzero(bzero_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
320  add_bzero(bzero_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
321  add_bzero(bzero)
322else()
323  add_bzero(bzero_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
324  add_bzero(bzero)
325endif()
326
327# ------------------------------------------------------------------------------
328# memcmp
329# ------------------------------------------------------------------------------
330
331function(add_memcmp memcmp_name)
332  add_implementation(memcmp ${memcmp_name}
333    SRCS ${LIBC_SOURCE_DIR}/src/string/memcmp.cpp
334    HDRS ${LIBC_SOURCE_DIR}/src/string/memcmp.h
335    DEPENDS
336      .memory_utils.memcmp_implementation
337      libc.include.string
338    COMPILE_OPTIONS
339      -fno-builtin-memcmp
340    ${ARGN}
341  )
342endfunction()
343
344if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
345  add_memcmp(memcmp_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
346  add_memcmp(memcmp_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
347  add_memcmp(memcmp_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
348  add_memcmp(memcmp_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
349  add_memcmp(memcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
350  add_memcmp(memcmp)
351elseif(${LIBC_TARGET_ARCHITECTURE_IS_AARCH64})
352  add_memcmp(memcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
353  add_memcmp(memcmp)
354else()
355  add_memcmp(memcmp_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
356  add_memcmp(memcmp)
357endif()
358
359# ------------------------------------------------------------------------------
360# memcpy
361# ------------------------------------------------------------------------------
362
363function(add_memcpy memcpy_name)
364  add_implementation(memcpy ${memcpy_name}
365    SRCS ${LIBC_SOURCE_DIR}/src/string/memcpy.cpp
366    HDRS ${LIBC_SOURCE_DIR}/src/string/memcpy.h
367    DEPENDS
368      .memory_utils.memcpy_implementation
369      libc.include.string
370    COMPILE_OPTIONS
371      -fno-builtin-memcpy
372    ${ARGN}
373  )
374endfunction()
375
376if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
377  add_memcpy(memcpy_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
378  add_memcpy(memcpy_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
379  add_memcpy(memcpy_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
380  add_memcpy(memcpy_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
381  add_memcpy(memcpy_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
382  add_memcpy(memcpy)
383elseif(${LIBC_TARGET_ARCHITECTURE_IS_AARCH64})
384  # Disable tail merging as it leads to lower performance.
385  # Note that '-mllvm' needs to be prefixed with 'SHELL:' to prevent CMake flag deduplication.
386  add_memcpy(memcpy_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE}
387                                      COMPILE_OPTIONS "SHELL:-mllvm --tail-merge-threshold=0")
388  add_memcpy(memcpy                   COMPILE_OPTIONS "SHELL:-mllvm --tail-merge-threshold=0")
389else()
390  add_memcpy(memcpy_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
391  add_memcpy(memcpy)
392endif()
393
394# ------------------------------------------------------------------------------
395# memmove
396# ------------------------------------------------------------------------------
397
398function(add_memmove memmove_name)
399  add_implementation(memmove ${memmove_name}
400    SRCS ${LIBC_SOURCE_DIR}/src/string/memmove.cpp
401    HDRS ${LIBC_SOURCE_DIR}/src/string/memmove.h
402    DEPENDS
403      .memory_utils.memory_utils
404      .memory_utils.memcpy_implementation
405      libc.include.string
406    COMPILE_OPTIONS
407      -fno-builtin
408    ${ARGN}
409  )
410endfunction()
411
412if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
413  add_memmove(memmove_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
414  add_memmove(memmove_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
415  add_memmove(memmove_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
416  add_memmove(memmove_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
417  add_memmove(memmove_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
418  add_memmove(memmove)
419elseif(${LIBC_TARGET_ARCHITECTURE_IS_AARCH64})
420  # Disable tail merging as it leads to lower performance.
421  # Note that '-mllvm' needs to be prefixed with 'SHELL:' to prevent CMake flag deduplication.
422  add_memmove(memmove_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE}
423                                        COMPILE_OPTIONS "SHELL:-mllvm --tail-merge-threshold=0")
424  add_memmove(memmove                   COMPILE_OPTIONS "SHELL:-mllvm --tail-merge-threshold=0")
425else()
426  add_memmove(memmove_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
427  add_memmove(memmove)
428endif()
429
430# ------------------------------------------------------------------------------
431# memset
432# ------------------------------------------------------------------------------
433
434function(add_memset memset_name)
435  add_implementation(memset ${memset_name}
436    SRCS ${LIBC_SOURCE_DIR}/src/string/memset.cpp
437    HDRS ${LIBC_SOURCE_DIR}/src/string/memset.h
438    DEPENDS
439      .memory_utils.memset_implementation
440      libc.include.string
441    COMPILE_OPTIONS
442      -fno-builtin-memset
443    ${ARGN}
444  )
445endfunction()
446
447if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
448  add_memset(memset_x86_64_opt_sse2   COMPILE_OPTIONS -march=k8             REQUIRE SSE2)
449  add_memset(memset_x86_64_opt_sse4   COMPILE_OPTIONS -march=nehalem        REQUIRE SSE4_2)
450  add_memset(memset_x86_64_opt_avx2   COMPILE_OPTIONS -march=haswell        REQUIRE AVX2)
451  add_memset(memset_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
452  add_memset(memset_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
453  add_memset(memset)
454elseif(${LIBC_TARGET_ARCHITECTURE_IS_AARCH64})
455  add_memset(memset_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE}
456                                      COMPILE_OPTIONS "SHELL:-mllvm --tail-merge-threshold=0")
457  add_memset(memset                   COMPILE_OPTIONS "SHELL:-mllvm --tail-merge-threshold=0")
458else()
459  add_memset(memset_opt_host          COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
460  add_memset(memset)
461endif()
462