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