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