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