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