@@ -175,6 +175,185 @@ class ilist_iterator : ilist_detail::SpecificNodeAccess<OptionsT> {
175
175
bool isEnd () const { return NodePtr ? NodePtr->isSentinel () : false ; }
176
176
};
177
177
178
+ // / Iterator for intrusive lists based on ilist_node. Much like ilist_iterator,
179
+ // / but with the addition of two bits recording whether this position (when in
180
+ // / a range) is half or fully open.
181
+ template <class OptionsT , bool IsReverse, bool IsConst>
182
+ class ilist_iterator_w_bits : ilist_detail::SpecificNodeAccess<OptionsT> {
183
+ friend ilist_iterator_w_bits<OptionsT, IsReverse, !IsConst>;
184
+ friend ilist_iterator_w_bits<OptionsT, !IsReverse, IsConst>;
185
+ friend ilist_iterator<OptionsT, !IsReverse, !IsConst>;
186
+
187
+ using Traits = ilist_detail::IteratorTraits<OptionsT, IsConst>;
188
+ using Access = ilist_detail::SpecificNodeAccess<OptionsT>;
189
+
190
+ public:
191
+ using value_type = typename Traits::value_type;
192
+ using pointer = typename Traits::pointer;
193
+ using reference = typename Traits::reference;
194
+ using difference_type = ptrdiff_t ;
195
+ using iterator_category = std::bidirectional_iterator_tag;
196
+ using const_pointer = typename OptionsT::const_pointer;
197
+ using const_reference = typename OptionsT::const_reference;
198
+
199
+ private:
200
+ using node_pointer = typename Traits::node_pointer;
201
+ using node_reference = typename Traits::node_reference;
202
+
203
+ node_pointer NodePtr = nullptr ;
204
+
205
+ #ifdef EXPERIMENTAL_DEBUGINFO_ITERATORS
206
+ // (Default: Off) Allow extra position-information flags to be stored
207
+ // in iterators, in aid of removing debug-info intrinsics from LLVM.
208
+
209
+ // / Is this position intended to contain any debug-info immediately before
210
+ // / the position?
211
+ mutable bool HeadInclusiveBit = false ;
212
+ // / Is this position intended to contain any debug-info immediately after
213
+ // / the position?
214
+ mutable bool TailInclusiveBit = false ;
215
+ #endif
216
+
217
+ public:
218
+ // / Create from an ilist_node.
219
+ explicit ilist_iterator_w_bits (node_reference N) : NodePtr(&N) {}
220
+
221
+ explicit ilist_iterator_w_bits (pointer NP)
222
+ : NodePtr(Access::getNodePtr(NP)) {}
223
+ explicit ilist_iterator_w_bits (reference NR)
224
+ : NodePtr(Access::getNodePtr(&NR)) {}
225
+ ilist_iterator_w_bits () = default ;
226
+
227
+ // This is templated so that we can allow constructing a const iterator from
228
+ // a nonconst iterator...
229
+ template <bool RHSIsConst>
230
+ ilist_iterator_w_bits (
231
+ const ilist_iterator_w_bits<OptionsT, IsReverse, RHSIsConst> &RHS,
232
+ std::enable_if_t <IsConst || !RHSIsConst, void *> = nullptr )
233
+ : NodePtr(RHS.NodePtr) {
234
+ #ifdef EXPERIMENTAL_DEBUGINFO_ITERATORS
235
+ HeadInclusiveBit = RHS.HeadInclusiveBit ;
236
+ TailInclusiveBit = RHS.TailInclusiveBit ;
237
+ #endif
238
+ }
239
+
240
+ // This is templated so that we can allow assigning to a const iterator from
241
+ // a nonconst iterator...
242
+ template <bool RHSIsConst>
243
+ std::enable_if_t <IsConst || !RHSIsConst, ilist_iterator_w_bits &>
244
+ operator =(const ilist_iterator_w_bits<OptionsT, IsReverse, RHSIsConst> &RHS) {
245
+ NodePtr = RHS.NodePtr ;
246
+ #ifdef EXPERIMENTAL_DEBUGINFO_ITERATORS
247
+ HeadInclusiveBit = RHS.HeadInclusiveBit ;
248
+ TailInclusiveBit = RHS.TailInclusiveBit ;
249
+ #endif
250
+ return *this ;
251
+ }
252
+
253
+ // / Explicit conversion between forward/reverse iterators.
254
+ // /
255
+ // / Translate between forward and reverse iterators without changing range
256
+ // / boundaries. The resulting iterator will dereference (and have a handle)
257
+ // / to the previous node, which is somewhat unexpected; but converting the
258
+ // / two endpoints in a range will give the same range in reverse.
259
+ // /
260
+ // / This matches std::reverse_iterator conversions.
261
+ explicit ilist_iterator_w_bits (
262
+ const ilist_iterator_w_bits<OptionsT, !IsReverse, IsConst> &RHS)
263
+ : ilist_iterator_w_bits(++RHS.getReverse()) {}
264
+
265
+ // / Get a reverse iterator to the same node.
266
+ // /
267
+ // / Gives a reverse iterator that will dereference (and have a handle) to the
268
+ // / same node. Converting the endpoint iterators in a range will give a
269
+ // / different range; for range operations, use the explicit conversions.
270
+ ilist_iterator_w_bits<OptionsT, !IsReverse, IsConst> getReverse () const {
271
+ if (NodePtr)
272
+ return ilist_iterator_w_bits<OptionsT, !IsReverse, IsConst>(*NodePtr);
273
+ return ilist_iterator_w_bits<OptionsT, !IsReverse, IsConst>();
274
+ }
275
+
276
+ // / Const-cast.
277
+ ilist_iterator_w_bits<OptionsT, IsReverse, false > getNonConst () const {
278
+ if (NodePtr) {
279
+ auto New = ilist_iterator_w_bits<OptionsT, IsReverse, false >(
280
+ const_cast <typename ilist_iterator_w_bits<OptionsT, IsReverse,
281
+ false >::node_reference>(
282
+ *NodePtr));
283
+ #ifdef EXPERIMENTAL_DEBUGINFO_ITERATORS
284
+ New.HeadInclusiveBit = HeadInclusiveBit;
285
+ New.TailInclusiveBit = TailInclusiveBit;
286
+ #endif
287
+ return New;
288
+ }
289
+ return ilist_iterator_w_bits<OptionsT, IsReverse, false >();
290
+ }
291
+
292
+ // Accessors...
293
+ reference operator *() const {
294
+ assert (!NodePtr->isKnownSentinel ());
295
+ return *Access::getValuePtr (NodePtr);
296
+ }
297
+ pointer operator ->() const { return &operator *(); }
298
+
299
+ // Comparison operators
300
+ friend bool operator ==(const ilist_iterator_w_bits &LHS,
301
+ const ilist_iterator_w_bits &RHS) {
302
+ return LHS.NodePtr == RHS.NodePtr ;
303
+ }
304
+ friend bool operator !=(const ilist_iterator_w_bits &LHS,
305
+ const ilist_iterator_w_bits &RHS) {
306
+ return LHS.NodePtr != RHS.NodePtr ;
307
+ }
308
+
309
+ // Increment and decrement operators...
310
+ ilist_iterator_w_bits &operator --() {
311
+ NodePtr = IsReverse ? NodePtr->getNext () : NodePtr->getPrev ();
312
+ #ifdef EXPERIMENTAL_DEBUGINFO_ITERATORS
313
+ HeadInclusiveBit = false ;
314
+ TailInclusiveBit = false ;
315
+ #endif
316
+ return *this ;
317
+ }
318
+ ilist_iterator_w_bits &operator ++() {
319
+ NodePtr = IsReverse ? NodePtr->getPrev () : NodePtr->getNext ();
320
+ #ifdef EXPERIMENTAL_DEBUGINFO_ITERATORS
321
+ HeadInclusiveBit = false ;
322
+ TailInclusiveBit = false ;
323
+ #endif
324
+ return *this ;
325
+ }
326
+ ilist_iterator_w_bits operator --(int ) {
327
+ ilist_iterator_w_bits tmp = *this ;
328
+ --*this ;
329
+ return tmp;
330
+ }
331
+ ilist_iterator_w_bits operator ++(int ) {
332
+ ilist_iterator_w_bits tmp = *this ;
333
+ ++*this ;
334
+ return tmp;
335
+ }
336
+
337
+ // / Get the underlying ilist_node.
338
+ node_pointer getNodePtr () const { return static_cast <node_pointer>(NodePtr); }
339
+
340
+ // / Check for end. Only valid if ilist_sentinel_tracking<true>.
341
+ bool isEnd () const { return NodePtr ? NodePtr->isSentinel () : false ; }
342
+
343
+ #ifdef EXPERIMENTAL_DEBUGINFO_ITERATORS
344
+ bool getHeadBit () const { return HeadInclusiveBit; }
345
+ bool getTailBit () const { return TailInclusiveBit; }
346
+ void setHeadBit (bool SetBit) const { HeadInclusiveBit = SetBit; }
347
+ void setTailBit (bool SetBit) const { TailInclusiveBit = SetBit; }
348
+ #else
349
+ // Store and return no information if we're not using this feature.
350
+ bool getHeadBit () const { return false ; }
351
+ bool getTailBit () const { return false ; }
352
+ void setHeadBit (bool SetBit) const { (void )SetBit; }
353
+ void setTailBit (bool SetBit) const { (void )SetBit; }
354
+ #endif
355
+ };
356
+
178
357
template <typename From> struct simplify_type ;
179
358
180
359
// / Allow ilist_iterators to convert into pointers to a node automatically when
@@ -192,6 +371,18 @@ template <class OptionsT, bool IsConst>
192
371
struct simplify_type <const ilist_iterator<OptionsT, false , IsConst>>
193
372
: simplify_type<ilist_iterator<OptionsT, false , IsConst>> {};
194
373
374
+ // ilist_iterator_w_bits should also be accessible via isa/dyn_cast.
375
+ template <class OptionsT , bool IsConst>
376
+ struct simplify_type <ilist_iterator_w_bits<OptionsT, false , IsConst>> {
377
+ using iterator = ilist_iterator_w_bits<OptionsT, false , IsConst>;
378
+ using SimpleType = typename iterator::pointer;
379
+
380
+ static SimpleType getSimplifiedValue (const iterator &Node) { return &*Node; }
381
+ };
382
+ template <class OptionsT , bool IsConst>
383
+ struct simplify_type <const ilist_iterator_w_bits<OptionsT, false , IsConst>>
384
+ : simplify_type<ilist_iterator_w_bits<OptionsT, false , IsConst>> {};
385
+
195
386
} // end namespace llvm
196
387
197
388
#endif // LLVM_ADT_ILIST_ITERATOR_H
0 commit comments