Check subrange liveness at rematerialization
[llvm-project.git] / libcxx / src / debug.cpp
blobae31c91d154f4d8a02f38821950f0df094210e53
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "__config"
10 #include "__debug"
11 #include "functional"
12 #include "algorithm"
13 #include "string"
14 #include "cstdio"
15 #include "__hash_table"
16 #ifndef _LIBCPP_HAS_NO_THREADS
17 #include "mutex"
18 #if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
19 #pragma comment(lib, "pthread")
20 #endif
21 #endif
23 _LIBCPP_BEGIN_NAMESPACE_STD
25 std::string __libcpp_debug_info::what() const {
26 string msg = __file_;
27 msg += ":" + to_string(__line_) + ": _LIBCPP_ASSERT '";
28 msg += __pred_;
29 msg += "' failed. ";
30 msg += __msg_;
31 return msg;
33 _LIBCPP_NORETURN void __libcpp_abort_debug_function(__libcpp_debug_info const& info) {
34 std::fprintf(stderr, "%s\n", info.what().c_str());
35 std::abort();
38 _LIBCPP_SAFE_STATIC __libcpp_debug_function_type
39 __libcpp_debug_function = __libcpp_abort_debug_function;
41 bool __libcpp_set_debug_function(__libcpp_debug_function_type __func) {
42 __libcpp_debug_function = __func;
43 return true;
46 _LIBCPP_FUNC_VIS
47 __libcpp_db*
48 __get_db()
50 static _LIBCPP_NO_DESTROY __libcpp_db db;
51 return &db;
54 _LIBCPP_FUNC_VIS
55 const __libcpp_db*
56 __get_const_db()
58 return __get_db();
61 namespace
64 #ifndef _LIBCPP_HAS_NO_THREADS
65 typedef mutex mutex_type;
66 typedef lock_guard<mutex_type> WLock;
67 typedef lock_guard<mutex_type> RLock;
69 mutex_type&
70 mut()
72 static _LIBCPP_NO_DESTROY mutex_type m;
73 return m;
75 #endif // !_LIBCPP_HAS_NO_THREADS
77 } // unnamed namespace
79 __i_node::~__i_node()
81 if (__next_)
83 __next_->~__i_node();
84 free(__next_);
88 __c_node::~__c_node()
90 free(beg_);
91 if (__next_)
93 __next_->~__c_node();
94 free(__next_);
98 __libcpp_db::__libcpp_db()
99 : __cbeg_(nullptr),
100 __cend_(nullptr),
101 __csz_(0),
102 __ibeg_(nullptr),
103 __iend_(nullptr),
104 __isz_(0)
108 __libcpp_db::~__libcpp_db()
110 if (__cbeg_)
112 for (__c_node** p = __cbeg_; p != __cend_; ++p)
114 if (*p != nullptr)
116 (*p)->~__c_node();
117 free(*p);
120 free(__cbeg_);
122 if (__ibeg_)
124 for (__i_node** p = __ibeg_; p != __iend_; ++p)
126 if (*p != nullptr)
128 (*p)->~__i_node();
129 free(*p);
132 free(__ibeg_);
136 void*
137 __libcpp_db::__find_c_from_i(void* __i) const
139 #ifndef _LIBCPP_HAS_NO_THREADS
140 RLock _(mut());
141 #endif
142 __i_node* i = __find_iterator(__i);
143 _LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database.");
144 return i->__c_ != nullptr ? i->__c_->__c_ : nullptr;
147 void
148 __libcpp_db::__insert_ic(void* __i, const void* __c)
150 #ifndef _LIBCPP_HAS_NO_THREADS
151 WLock _(mut());
152 #endif
153 if (__cbeg_ == __cend_)
154 return;
155 size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
156 __c_node* c = __cbeg_[hc];
157 if (c == nullptr)
158 return;
159 while (c->__c_ != __c)
161 c = c->__next_;
162 if (c == nullptr)
163 return;
165 __i_node* i = __insert_iterator(__i);
166 c->__add(i);
167 i->__c_ = c;
170 void
171 __libcpp_db::__insert_c(void* __c, __libcpp_db::_InsertConstruct *__fn)
173 #ifndef _LIBCPP_HAS_NO_THREADS
174 WLock _(mut());
175 #endif
176 if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_))
178 size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1);
179 __c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(__c_node*)));
180 if (cbeg == nullptr)
181 __throw_bad_alloc();
183 for (__c_node** p = __cbeg_; p != __cend_; ++p)
185 __c_node* q = *p;
186 while (q != nullptr)
188 size_t h = hash<void*>()(q->__c_) % nc;
189 __c_node* r = q->__next_;
190 q->__next_ = cbeg[h];
191 cbeg[h] = q;
192 q = r;
195 free(__cbeg_);
196 __cbeg_ = cbeg;
197 __cend_ = __cbeg_ + nc;
199 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
200 __c_node* p = __cbeg_[hc];
201 void *buf = malloc(sizeof(__c_node));
202 if (buf == nullptr)
203 __throw_bad_alloc();
204 __cbeg_[hc] = __fn(buf, __c, p);
206 ++__csz_;
209 void
210 __libcpp_db::__erase_i(void* __i)
212 #ifndef _LIBCPP_HAS_NO_THREADS
213 WLock _(mut());
214 #endif
215 if (__ibeg_ != __iend_)
217 size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
218 __i_node* p = __ibeg_[hi];
219 if (p != nullptr)
221 __i_node* q = nullptr;
222 while (p->__i_ != __i)
224 q = p;
225 p = p->__next_;
226 if (p == nullptr)
227 return;
229 if (q == nullptr)
230 __ibeg_[hi] = p->__next_;
231 else
232 q->__next_ = p->__next_;
233 __c_node* c = p->__c_;
234 --__isz_;
235 if (c != nullptr)
236 c->__remove(p);
237 free(p);
242 void
243 __libcpp_db::__invalidate_all(void* __c)
245 #ifndef _LIBCPP_HAS_NO_THREADS
246 WLock _(mut());
247 #endif
248 if (__cend_ != __cbeg_)
250 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
251 __c_node* p = __cbeg_[hc];
252 if (p == nullptr)
253 return;
254 while (p->__c_ != __c)
256 p = p->__next_;
257 if (p == nullptr)
258 return;
260 while (p->end_ != p->beg_)
262 --p->end_;
263 (*p->end_)->__c_ = nullptr;
268 __c_node*
269 __libcpp_db::__find_c_and_lock(void* __c) const
271 #ifndef _LIBCPP_HAS_NO_THREADS
272 mut().lock();
273 #endif
274 if (__cend_ == __cbeg_)
276 #ifndef _LIBCPP_HAS_NO_THREADS
277 mut().unlock();
278 #endif
279 return nullptr;
281 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
282 __c_node* p = __cbeg_[hc];
283 if (p == nullptr)
285 #ifndef _LIBCPP_HAS_NO_THREADS
286 mut().unlock();
287 #endif
288 return nullptr;
290 while (p->__c_ != __c)
292 p = p->__next_;
293 if (p == nullptr)
295 #ifndef _LIBCPP_HAS_NO_THREADS
296 mut().unlock();
297 #endif
298 return nullptr;
301 return p;
304 __c_node*
305 __libcpp_db::__find_c(void* __c) const
307 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
308 __c_node* p = __cbeg_[hc];
309 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A");
310 while (p->__c_ != __c)
312 p = p->__next_;
313 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B");
315 return p;
318 void
319 __libcpp_db::unlock() const
321 #ifndef _LIBCPP_HAS_NO_THREADS
322 mut().unlock();
323 #endif
326 void
327 __libcpp_db::__erase_c(void* __c)
329 #ifndef _LIBCPP_HAS_NO_THREADS
330 WLock _(mut());
331 #endif
332 if (__cend_ != __cbeg_)
334 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
335 __c_node* p = __cbeg_[hc];
336 if (p == nullptr)
337 return;
338 __c_node* q = nullptr;
339 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A");
340 while (p->__c_ != __c)
342 q = p;
343 p = p->__next_;
344 if (p == nullptr)
345 return;
346 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B");
348 if (q == nullptr)
349 __cbeg_[hc] = p->__next_;
350 else
351 q->__next_ = p->__next_;
352 while (p->end_ != p->beg_)
354 --p->end_;
355 (*p->end_)->__c_ = nullptr;
357 free(p->beg_);
358 free(p);
359 --__csz_;
363 void
364 __libcpp_db::__iterator_copy(void* __i, const void* __i0)
366 #ifndef _LIBCPP_HAS_NO_THREADS
367 WLock _(mut());
368 #endif
369 __i_node* i = __find_iterator(__i);
370 __i_node* i0 = __find_iterator(__i0);
371 __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr;
372 if (i == nullptr && i0 != nullptr)
373 i = __insert_iterator(__i);
374 __c_node* c = i != nullptr ? i->__c_ : nullptr;
375 if (c != c0)
377 if (c != nullptr)
378 c->__remove(i);
379 if (i != nullptr)
381 i->__c_ = nullptr;
382 if (c0 != nullptr)
384 i->__c_ = c0;
385 i->__c_->__add(i);
391 bool
392 __libcpp_db::__dereferenceable(const void* __i) const
394 #ifndef _LIBCPP_HAS_NO_THREADS
395 RLock _(mut());
396 #endif
397 __i_node* i = __find_iterator(__i);
398 return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i);
401 bool
402 __libcpp_db::__decrementable(const void* __i) const
404 #ifndef _LIBCPP_HAS_NO_THREADS
405 RLock _(mut());
406 #endif
407 __i_node* i = __find_iterator(__i);
408 return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i);
411 bool
412 __libcpp_db::__addable(const void* __i, ptrdiff_t __n) const
414 #ifndef _LIBCPP_HAS_NO_THREADS
415 RLock _(mut());
416 #endif
417 __i_node* i = __find_iterator(__i);
418 return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n);
421 bool
422 __libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const
424 #ifndef _LIBCPP_HAS_NO_THREADS
425 RLock _(mut());
426 #endif
427 __i_node* i = __find_iterator(__i);
428 return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n);
431 bool
432 __libcpp_db::__less_than_comparable(const void* __i, const void* __j) const
434 #ifndef _LIBCPP_HAS_NO_THREADS
435 RLock _(mut());
436 #endif
437 __i_node* i = __find_iterator(__i);
438 __i_node* j = __find_iterator(__j);
439 __c_node* ci = i != nullptr ? i->__c_ : nullptr;
440 __c_node* cj = j != nullptr ? j->__c_ : nullptr;
441 return ci == cj;
444 void
445 __libcpp_db::swap(void* c1, void* c2)
447 #ifndef _LIBCPP_HAS_NO_THREADS
448 WLock _(mut());
449 #endif
450 size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_);
451 __c_node* p1 = __cbeg_[hc];
452 _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A");
453 while (p1->__c_ != c1)
455 p1 = p1->__next_;
456 _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B");
458 hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_);
459 __c_node* p2 = __cbeg_[hc];
460 _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C");
461 while (p2->__c_ != c2)
463 p2 = p2->__next_;
464 _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D");
466 std::swap(p1->beg_, p2->beg_);
467 std::swap(p1->end_, p2->end_);
468 std::swap(p1->cap_, p2->cap_);
469 for (__i_node** p = p1->beg_; p != p1->end_; ++p)
470 (*p)->__c_ = p1;
471 for (__i_node** p = p2->beg_; p != p2->end_; ++p)
472 (*p)->__c_ = p2;
475 void
476 __libcpp_db::__insert_i(void* __i)
478 #ifndef _LIBCPP_HAS_NO_THREADS
479 WLock _(mut());
480 #endif
481 __insert_iterator(__i);
484 void
485 __c_node::__add(__i_node* i)
487 if (end_ == cap_)
489 size_t nc = 2*static_cast<size_t>(cap_ - beg_);
490 if (nc == 0)
491 nc = 1;
492 __i_node** beg =
493 static_cast<__i_node**>(malloc(nc * sizeof(__i_node*)));
494 if (beg == nullptr)
495 __throw_bad_alloc();
497 if (nc > 1)
498 memcpy(beg, beg_, nc/2*sizeof(__i_node*));
499 free(beg_);
500 beg_ = beg;
501 end_ = beg_ + nc/2;
502 cap_ = beg_ + nc;
504 *end_++ = i;
507 // private api
509 _LIBCPP_HIDDEN
510 __i_node*
511 __libcpp_db::__insert_iterator(void* __i)
513 if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_))
515 size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1);
516 __i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(__i_node*)));
517 if (ibeg == nullptr)
518 __throw_bad_alloc();
520 for (__i_node** p = __ibeg_; p != __iend_; ++p)
522 __i_node* q = *p;
523 while (q != nullptr)
525 size_t h = hash<void*>()(q->__i_) % nc;
526 __i_node* r = q->__next_;
527 q->__next_ = ibeg[h];
528 ibeg[h] = q;
529 q = r;
532 free(__ibeg_);
533 __ibeg_ = ibeg;
534 __iend_ = __ibeg_ + nc;
536 size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
537 __i_node* p = __ibeg_[hi];
538 __i_node* r = __ibeg_[hi] =
539 static_cast<__i_node*>(malloc(sizeof(__i_node)));
540 if (r == nullptr)
541 __throw_bad_alloc();
543 ::new(r) __i_node(__i, p, nullptr);
544 ++__isz_;
545 return r;
548 _LIBCPP_HIDDEN
549 __i_node*
550 __libcpp_db::__find_iterator(const void* __i) const
552 __i_node* r = nullptr;
553 if (__ibeg_ != __iend_)
555 size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
556 for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_)
558 if (nd->__i_ == __i)
560 r = nd;
561 break;
565 return r;
568 _LIBCPP_HIDDEN
569 void
570 __c_node::__remove(__i_node* p)
572 __i_node** r = find(beg_, end_, p);
573 _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove");
574 if (--end_ != r)
575 memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*));
578 _LIBCPP_END_NAMESPACE_STD