sanitizer_range.cpp 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. //===-- sanitizer_range.cpp -----------------------------------------------===//
  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. //===----------------------------------------------------------------------===//
  8. #include "sanitizer_range.h"
  9. #include "sanitizer_common/sanitizer_array_ref.h"
  10. namespace __sanitizer {
  11. void Intersect(ArrayRef<Range> a, ArrayRef<Range> b,
  12. InternalMmapVectorNoCtor<Range> &output) {
  13. output.clear();
  14. struct Event {
  15. uptr val;
  16. s8 diff1;
  17. s8 diff2;
  18. };
  19. InternalMmapVector<Event> events;
  20. for (const Range &r : a) {
  21. CHECK_LE(r.begin, r.end);
  22. events.push_back({r.begin, 1, 0});
  23. events.push_back({r.end, -1, 0});
  24. }
  25. for (const Range &r : b) {
  26. CHECK_LE(r.begin, r.end);
  27. events.push_back({r.begin, 0, 1});
  28. events.push_back({r.end, 0, -1});
  29. }
  30. Sort(events.data(), events.size(),
  31. [](const Event &lh, const Event &rh) { return lh.val < rh.val; });
  32. uptr start = 0;
  33. sptr state1 = 0;
  34. sptr state2 = 0;
  35. for (const auto &e : events) {
  36. if (e.val != start) {
  37. DCHECK_GE(state1, 0);
  38. DCHECK_GE(state2, 0);
  39. if (state1 && state2) {
  40. if (!output.empty() && start == output.back().end)
  41. output.back().end = e.val;
  42. else
  43. output.push_back({start, e.val});
  44. }
  45. start = e.val;
  46. }
  47. state1 += e.diff1;
  48. state2 += e.diff2;
  49. }
  50. }
  51. } // namespace __sanitizer