[AArch64] Add cost handling of CALLER_SAVE_REGS and POINTER_REGS
[official-gcc.git] / libsanitizer / sanitizer_common / sanitizer_libc.cc
blobc13a66d88cde4e1e8291bfcd38a7d6b4d1e84b46
1 //===-- sanitizer_libc.cc -------------------------------------------------===//
2 //
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file is shared between AddressSanitizer and ThreadSanitizer
9 // run-time libraries. See sanitizer_libc.h for details.
10 //===----------------------------------------------------------------------===//
11 #include "sanitizer_allocator_internal.h"
12 #include "sanitizer_common.h"
13 #include "sanitizer_libc.h"
15 namespace __sanitizer {
17 // Make the compiler think that something is going on there.
18 static inline void break_optimization(void *arg) {
19 #if _MSC_VER
20 // FIXME: make sure this is actually enough.
21 __asm;
22 #else
23 __asm__ __volatile__("" : : "r" (arg) : "memory");
24 #endif
27 s64 internal_atoll(const char *nptr) {
28 return internal_simple_strtoll(nptr, (char**)0, 10);
31 void *internal_memchr(const void *s, int c, uptr n) {
32 const char* t = (char*)s;
33 for (uptr i = 0; i < n; ++i, ++t)
34 if (*t == c)
35 return (void*)t;
36 return 0;
39 int internal_memcmp(const void* s1, const void* s2, uptr n) {
40 const char* t1 = (char*)s1;
41 const char* t2 = (char*)s2;
42 for (uptr i = 0; i < n; ++i, ++t1, ++t2)
43 if (*t1 != *t2)
44 return *t1 < *t2 ? -1 : 1;
45 return 0;
48 void *internal_memcpy(void *dest, const void *src, uptr n) {
49 char *d = (char*)dest;
50 char *s = (char*)src;
51 for (uptr i = 0; i < n; ++i)
52 d[i] = s[i];
53 return dest;
56 void *internal_memmove(void *dest, const void *src, uptr n) {
57 char *d = (char*)dest;
58 char *s = (char*)src;
59 sptr i, signed_n = (sptr)n;
60 CHECK_GE(signed_n, 0);
61 if (d < s) {
62 for (i = 0; i < signed_n; ++i)
63 d[i] = s[i];
64 } else {
65 if (d > s && signed_n > 0)
66 for (i = signed_n - 1; i >= 0 ; --i) {
67 d[i] = s[i];
70 return dest;
73 // Semi-fast bzero for 16-aligned data. Still far from peak performance.
74 void internal_bzero_aligned16(void *s, uptr n) {
75 struct S16 { u64 a, b; } ALIGNED(16);
76 CHECK_EQ((reinterpret_cast<uptr>(s) | n) & 15, 0);
77 for (S16 *p = reinterpret_cast<S16*>(s), *end = p + n / 16; p < end; p++) {
78 p->a = p->b = 0;
79 break_optimization(0); // Make sure this does not become memset.
83 void *internal_memset(void* s, int c, uptr n) {
84 // The next line prevents Clang from making a call to memset() instead of the
85 // loop below.
86 // FIXME: building the runtime with -ffreestanding is a better idea. However
87 // there currently are linktime problems due to PR12396.
88 char volatile *t = (char*)s;
89 for (uptr i = 0; i < n; ++i, ++t) {
90 *t = c;
92 return s;
95 uptr internal_strcspn(const char *s, const char *reject) {
96 uptr i;
97 for (i = 0; s[i]; i++) {
98 if (internal_strchr(reject, s[i]) != 0)
99 return i;
101 return i;
104 char* internal_strdup(const char *s) {
105 uptr len = internal_strlen(s);
106 char *s2 = (char*)InternalAlloc(len + 1);
107 internal_memcpy(s2, s, len);
108 s2[len] = 0;
109 return s2;
112 int internal_strcmp(const char *s1, const char *s2) {
113 while (true) {
114 unsigned c1 = *s1;
115 unsigned c2 = *s2;
116 if (c1 != c2) return (c1 < c2) ? -1 : 1;
117 if (c1 == 0) break;
118 s1++;
119 s2++;
121 return 0;
124 int internal_strncmp(const char *s1, const char *s2, uptr n) {
125 for (uptr i = 0; i < n; i++) {
126 unsigned c1 = *s1;
127 unsigned c2 = *s2;
128 if (c1 != c2) return (c1 < c2) ? -1 : 1;
129 if (c1 == 0) break;
130 s1++;
131 s2++;
133 return 0;
136 char* internal_strchr(const char *s, int c) {
137 while (true) {
138 if (*s == (char)c)
139 return (char*)s;
140 if (*s == 0)
141 return 0;
142 s++;
146 char *internal_strchrnul(const char *s, int c) {
147 char *res = internal_strchr(s, c);
148 if (!res)
149 res = (char*)s + internal_strlen(s);
150 return res;
153 char *internal_strrchr(const char *s, int c) {
154 const char *res = 0;
155 for (uptr i = 0; s[i]; i++) {
156 if (s[i] == c) res = s + i;
158 return (char*)res;
161 uptr internal_strlen(const char *s) {
162 uptr i = 0;
163 while (s[i]) i++;
164 return i;
167 char *internal_strncat(char *dst, const char *src, uptr n) {
168 uptr len = internal_strlen(dst);
169 uptr i;
170 for (i = 0; i < n && src[i]; i++)
171 dst[len + i] = src[i];
172 dst[len + i] = 0;
173 return dst;
176 char *internal_strncpy(char *dst, const char *src, uptr n) {
177 uptr i;
178 for (i = 0; i < n && src[i]; i++)
179 dst[i] = src[i];
180 internal_memset(dst + i, '\0', n - i);
181 return dst;
184 uptr internal_strnlen(const char *s, uptr maxlen) {
185 uptr i = 0;
186 while (i < maxlen && s[i]) i++;
187 return i;
190 char *internal_strstr(const char *haystack, const char *needle) {
191 // This is O(N^2), but we are not using it in hot places.
192 uptr len1 = internal_strlen(haystack);
193 uptr len2 = internal_strlen(needle);
194 if (len1 < len2) return 0;
195 for (uptr pos = 0; pos <= len1 - len2; pos++) {
196 if (internal_memcmp(haystack + pos, needle, len2) == 0)
197 return (char*)haystack + pos;
199 return 0;
202 s64 internal_simple_strtoll(const char *nptr, char **endptr, int base) {
203 CHECK_EQ(base, 10);
204 while (IsSpace(*nptr)) nptr++;
205 int sgn = 1;
206 u64 res = 0;
207 bool have_digits = false;
208 char *old_nptr = (char*)nptr;
209 if (*nptr == '+') {
210 sgn = 1;
211 nptr++;
212 } else if (*nptr == '-') {
213 sgn = -1;
214 nptr++;
216 while (IsDigit(*nptr)) {
217 res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX;
218 int digit = ((*nptr) - '0');
219 res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX;
220 have_digits = true;
221 nptr++;
223 if (endptr != 0) {
224 *endptr = (have_digits) ? (char*)nptr : old_nptr;
226 if (sgn > 0) {
227 return (s64)(Min((u64)INT64_MAX, res));
228 } else {
229 return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1);
233 bool mem_is_zero(const char *beg, uptr size) {
234 CHECK_LE(size, 1ULL << FIRST_32_SECOND_64(30, 40)); // Sanity check.
235 const char *end = beg + size;
236 uptr *aligned_beg = (uptr *)RoundUpTo((uptr)beg, sizeof(uptr));
237 uptr *aligned_end = (uptr *)RoundDownTo((uptr)end, sizeof(uptr));
238 uptr all = 0;
239 // Prologue.
240 for (const char *mem = beg; mem < (char*)aligned_beg && mem < end; mem++)
241 all |= *mem;
242 // Aligned loop.
243 for (; aligned_beg < aligned_end; aligned_beg++)
244 all |= *aligned_beg;
245 // Epilogue.
246 if ((char*)aligned_end >= beg)
247 for (const char *mem = (char*)aligned_end; mem < end; mem++)
248 all |= *mem;
249 return all == 0;
252 } // namespace __sanitizer