1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | #ifndef LLVM_CLANG_ANALYSIS_SUPPORT_BUMPVECTOR_H |
19 | #define LLVM_CLANG_ANALYSIS_SUPPORT_BUMPVECTOR_H |
20 | |
21 | #include "llvm/ADT/PointerIntPair.h" |
22 | #include "llvm/Support/Allocator.h" |
23 | #include <cassert> |
24 | #include <cstddef> |
25 | #include <cstring> |
26 | #include <iterator> |
27 | #include <memory> |
28 | #include <type_traits> |
29 | |
30 | namespace clang { |
31 | |
32 | class BumpVectorContext { |
33 | llvm::PointerIntPair<llvm::BumpPtrAllocator*, 1> Alloc; |
34 | |
35 | public: |
36 | |
37 | |
38 | BumpVectorContext() : Alloc(new llvm::BumpPtrAllocator(), 1) {} |
39 | |
40 | BumpVectorContext(BumpVectorContext &&Other) : Alloc(Other.Alloc) { |
41 | Other.Alloc.setInt(false); |
42 | Other.Alloc.setPointer(nullptr); |
43 | } |
44 | |
45 | |
46 | |
47 | |
48 | BumpVectorContext(llvm::BumpPtrAllocator &A) : Alloc(&A, 0) {} |
49 | |
50 | ~BumpVectorContext() { |
51 | if (Alloc.getInt()) |
52 | delete Alloc.getPointer(); |
53 | } |
54 | |
55 | llvm::BumpPtrAllocator &getAllocator() { return *Alloc.getPointer(); } |
56 | }; |
57 | |
58 | template<typename T> |
59 | class BumpVector { |
60 | T *Begin = nullptr; |
61 | T *End = nullptr; |
62 | T *Capacity = nullptr; |
63 | |
64 | public: |
65 | |
66 | explicit BumpVector(BumpVectorContext &C, unsigned N) { |
67 | reserve(C, N); |
68 | } |
69 | |
70 | ~BumpVector() { |
71 | if (std::is_class<T>::value) { |
72 | |
73 | destroy_range(Begin, End); |
74 | } |
75 | } |
76 | |
77 | using size_type = size_t; |
78 | using difference_type = ptrdiff_t; |
79 | using value_type = T; |
80 | using iterator = T *; |
81 | using const_iterator = const T *; |
82 | |
83 | using const_reverse_iterator = std::reverse_iterator<const_iterator>; |
84 | using reverse_iterator = std::reverse_iterator<iterator>; |
85 | |
86 | using reference = T &; |
87 | using const_reference = const T &; |
88 | using pointer = T *; |
89 | using const_pointer = const T *; |
90 | |
91 | |
92 | iterator begin() { return Begin; } |
93 | const_iterator begin() const { return Begin; } |
94 | iterator end() { return End; } |
95 | const_iterator end() const { return End; } |
96 | |
97 | |
98 | reverse_iterator rbegin() { return reverse_iterator(end()); } |
99 | const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } |
100 | reverse_iterator rend() { return reverse_iterator(begin()); } |
101 | const_reverse_iterator rend() const { |
102 | return const_reverse_iterator(begin()); |
103 | } |
104 | |
105 | bool empty() const { return Begin == End; } |
106 | size_type size() const { return End-Begin; } |
107 | |
108 | reference operator[](unsigned idx) { |
109 | assert(Begin + idx < End); |
110 | return Begin[idx]; |
111 | } |
112 | const_reference operator[](unsigned idx) const { |
113 | assert(Begin + idx < End); |
114 | return Begin[idx]; |
115 | } |
116 | |
117 | reference front() { |
118 | return begin()[0]; |
119 | } |
120 | const_reference front() const { |
121 | return begin()[0]; |
122 | } |
123 | |
124 | reference back() { |
125 | return end()[-1]; |
126 | } |
127 | const_reference back() const { |
128 | return end()[-1]; |
129 | } |
130 | |
131 | void pop_back() { |
132 | --End; |
133 | End->~T(); |
134 | } |
135 | |
136 | T pop_back_val() { |
137 | T Result = back(); |
138 | pop_back(); |
139 | return Result; |
140 | } |
141 | |
142 | void clear() { |
143 | if (std::is_class<T>::value) { |
144 | destroy_range(Begin, End); |
145 | } |
146 | End = Begin; |
147 | } |
148 | |
149 | |
150 | pointer data() { |
151 | return pointer(Begin); |
152 | } |
153 | |
154 | |
155 | const_pointer data() const { |
156 | return const_pointer(Begin); |
157 | } |
158 | |
159 | void push_back(const_reference Elt, BumpVectorContext &C) { |
160 | if (End < Capacity) { |
161 | Retry: |
162 | new (End) T(Elt); |
163 | ++End; |
164 | return; |
165 | } |
166 | grow(C); |
167 | goto Retry; |
168 | } |
169 | |
170 | |
171 | |
172 | iterator insert(iterator I, size_t Cnt, const_reference E, |
173 | BumpVectorContext &C) { |
174 | (0) . __assert_fail ("I >= Begin && I <= End && \"Iterator out of bounds.\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Analysis/Support/BumpVector.h", 174, __PRETTY_FUNCTION__))" file_link="../../../../../include/assert.h.html#88" macro="true">assert(I >= Begin && I <= End && "Iterator out of bounds."); |
175 | if (End + Cnt <= Capacity) { |
176 | Retry: |
177 | move_range_right(I, End, Cnt); |
178 | construct_range(I, I + Cnt, E); |
179 | End += Cnt; |
180 | return I + Cnt; |
181 | } |
182 | ptrdiff_t D = I - Begin; |
183 | grow(C, size() + Cnt); |
184 | I = Begin + D; |
185 | goto Retry; |
186 | } |
187 | |
188 | void reserve(BumpVectorContext &C, unsigned N) { |
189 | if (unsigned(Capacity-Begin) < N) |
190 | grow(C, N); |
191 | } |
192 | |
193 | |
194 | |
195 | size_t capacity() const { return Capacity - Begin; } |
196 | |
197 | private: |
198 | |
199 | |
200 | void grow(BumpVectorContext &C, size_type MinSize = 1); |
201 | |
202 | void construct_range(T *S, T *E, const T &Elt) { |
203 | for (; S != E; ++S) |
204 | new (S) T(Elt); |
205 | } |
206 | |
207 | void destroy_range(T *S, T *E) { |
208 | while (S != E) { |
209 | --E; |
210 | E->~T(); |
211 | } |
212 | } |
213 | |
214 | void move_range_right(T *S, T *E, size_t D) { |
215 | for (T *I = E + D - 1, *IL = S + D - 1; I != IL; --I) { |
216 | --E; |
217 | new (I) T(*E); |
218 | E->~T(); |
219 | } |
220 | } |
221 | }; |
222 | |
223 | |
224 | template <typename T> |
225 | void BumpVector<T>::grow(BumpVectorContext &C, size_t MinSize) { |
226 | size_t CurCapacity = Capacity-Begin; |
227 | size_t CurSize = size(); |
228 | size_t NewCapacity = 2*CurCapacity; |
229 | if (NewCapacity < MinSize) |
230 | NewCapacity = MinSize; |
231 | |
232 | |
233 | T *NewElts = C.getAllocator().template Allocate<T>(NewCapacity); |
234 | |
235 | |
236 | if (Begin != End) { |
237 | if (std::is_class<T>::value) { |
238 | std::uninitialized_copy(Begin, End, NewElts); |
239 | |
240 | destroy_range(Begin, End); |
241 | } else { |
242 | |
243 | memcpy(NewElts, Begin, CurSize * sizeof(T)); |
244 | } |
245 | } |
246 | |
247 | |
248 | |
249 | Begin = NewElts; |
250 | End = NewElts+CurSize; |
251 | Capacity = Begin+NewCapacity; |
252 | } |
253 | |
254 | } |
255 | |
256 | #endif |
257 | |