xref: /freebsd/contrib/llvm-project/compiler-rt/lib/orc/record_section_tracker.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- record_section_tracker.h -- for fixed-sized record sects -*- C++ -*-===//
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 //
9 // RecordSectionsTracker: Responsible for managing sections of metadata records
10 // with fixed sizes.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef ORC_RT_RECORD_SECTION_TRACKER_H
15 #define ORC_RT_RECORD_SECTION_TRACKER_H
16 
17 #include "error.h"
18 #include "executor_address.h"
19 #include <algorithm>
20 #include <vector>
21 
22 namespace orc_rt {
23 
24 /// Used to manage sections of fixed-sized metadata records (e.g. pointer
25 /// sections, selector refs, etc.)
26 template <typename RecordElement> class RecordSectionsTracker {
27 public:
28   /// Add a section to the "new" list.
add(span<RecordElement> Sec)29   void add(span<RecordElement> Sec) { New.push_back(std::move(Sec)); }
30 
31   /// Returns true if there are new sections to process.
hasNewSections()32   bool hasNewSections() const { return !New.empty(); }
33 
34   /// Returns the number of new sections to process.
numNewSections()35   size_t numNewSections() const { return New.size(); }
36 
37   /// Process all new sections.
38   template <typename ProcessSectionFunc>
39   std::enable_if_t<std::is_void_v<
40       std::invoke_result_t<ProcessSectionFunc, span<RecordElement>>>>
processNewSections(ProcessSectionFunc && ProcessSection)41   processNewSections(ProcessSectionFunc &&ProcessSection) {
42     for (auto &Sec : New)
43       ProcessSection(Sec);
44     moveNewToProcessed();
45   }
46 
47   /// Proces all new sections with a fallible handler.
48   ///
49   /// Successfully handled sections will be moved to the Processed
50   /// list.
51   template <typename ProcessSectionFunc>
52   std::enable_if_t<
53       std::is_same_v<
54           Error, std::invoke_result_t<ProcessSectionFunc, span<RecordElement>>>,
55       Error>
processNewSections(ProcessSectionFunc && ProcessSection)56   processNewSections(ProcessSectionFunc &&ProcessSection) {
57     for (size_t I = 0; I != New.size(); ++I) {
58       if (auto Err = ProcessSection(New[I])) {
59         for (size_t J = 0; J != I; ++J)
60           Processed.push_back(New[J]);
61         New.erase(New.begin(), New.begin() + I);
62         return Err;
63       }
64     }
65     moveNewToProcessed();
66     return Error::success();
67   }
68 
69   /// Move all sections back to New for reprocessing.
reset()70   void reset() {
71     moveNewToProcessed();
72     New = std::move(Processed);
73   }
74 
75   /// Remove the section with the given range.
removeIfPresent(ExecutorAddrRange R)76   bool removeIfPresent(ExecutorAddrRange R) {
77     if (removeIfPresent(New, R))
78       return true;
79     return removeIfPresent(Processed, R);
80   }
81 
82 private:
moveNewToProcessed()83   void moveNewToProcessed() {
84     if (Processed.empty())
85       Processed = std::move(New);
86     else {
87       Processed.reserve(Processed.size() + New.size());
88       std::copy(New.begin(), New.end(), std::back_inserter(Processed));
89       New.clear();
90     }
91   }
92 
removeIfPresent(std::vector<span<RecordElement>> & V,ExecutorAddrRange R)93   bool removeIfPresent(std::vector<span<RecordElement>> &V,
94                        ExecutorAddrRange R) {
95     auto RI = std::find_if(
96         V.rbegin(), V.rend(),
97         [RS = R.toSpan<RecordElement>()](const span<RecordElement> &E) {
98           return E.data() == RS.data();
99         });
100     if (RI != V.rend()) {
101       V.erase(std::next(RI).base());
102       return true;
103     }
104     return false;
105   }
106 
107   std::vector<span<RecordElement>> Processed;
108   std::vector<span<RecordElement>> New;
109 };
110 
111 } // namespace orc_rt
112 
113 #endif // ORC_RT_RECORD_SECTION_TRACKER_H
114