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