@@ -204,42 +204,58 @@ struct allMemoryKinds
204
204
}
205
205
};
206
206
207
+ // Base class for forward iterators over the predecessor edge linked list.
208
+ // Subclasses decide what the iterator yields (edge, source block, etc.) by implementing the dereference operator.
209
+ // The pred list cannot be modified during iteration unless allowEdits is true.
210
+ //
211
+ template <bool allowEdits>
212
+ class BasePredIterator
213
+ {
214
+ private:
215
+ // When allowEdits=false, try to guard against the user of the iterator from modifying the predecessor list
216
+ // being traversed: cache the edge we think should be next, then check it when we actually do the `++`
217
+ // operation. This is a bit conservative, but attempts to protect against callers assuming too much about
218
+ // this iterator implementation.
219
+ // When allowEdits=true, m_next is always used to update m_pred, so changes to m_pred don't break the iterator.
220
+ FlowEdge* m_next;
221
+
222
+ protected:
223
+ FlowEdge* m_pred;
224
+
225
+ BasePredIterator (FlowEdge* pred);
226
+
227
+ public:
228
+ BasePredIterator& operator ++();
229
+
230
+ bool operator !=(const BasePredIterator& i) const
231
+ {
232
+ return m_pred != i.m_pred ;
233
+ }
234
+ };
235
+
207
236
// PredEdgeList: adapter class for forward iteration of the predecessor edge linked list using range-based `for`,
208
237
// normally used via BasicBlock::PredEdges(), e.g.:
209
238
// for (FlowEdge* const edge : block->PredEdges()) ...
239
+ // allowEdits controls whether the iterator should be resilient to changes to the predecessor list.
210
240
//
241
+ template <bool allowEdits>
211
242
class PredEdgeList
212
243
{
213
244
FlowEdge* m_begin;
214
245
215
246
// Forward iterator for the predecessor edges linked list.
216
- // The caller can't make changes to the preds list when using this.
217
247
//
218
- class iterator
248
+ class PredEdgeIterator : public BasePredIterator <allowEdits>
219
249
{
220
- FlowEdge* m_pred;
221
-
222
- #ifdef DEBUG
223
- // Try to guard against the user of the iterator from making changes to the IR that would invalidate
224
- // the iterator: cache the edge we think should be next, then check it when we actually do the `++`
225
- // operation. This is a bit conservative, but attempts to protect against callers assuming too much about
226
- // this iterator implementation.
227
- FlowEdge* m_next;
228
- #endif
229
-
230
250
public:
231
- iterator (FlowEdge* pred);
232
-
233
- FlowEdge* operator *() const
251
+ PredEdgeIterator (FlowEdge* pred)
252
+ : BasePredIterator<allowEdits>(pred)
234
253
{
235
- return m_pred;
236
254
}
237
255
238
- iterator& operator ++();
239
-
240
- bool operator !=(const iterator& i) const
256
+ FlowEdge* operator *() const
241
257
{
242
- return m_pred != i. m_pred ;
258
+ return this -> m_pred ;
243
259
}
244
260
};
245
261
@@ -249,14 +265,14 @@ class PredEdgeList
249
265
{
250
266
}
251
267
252
- iterator begin () const
268
+ PredEdgeIterator begin () const
253
269
{
254
- return iterator (m_begin);
270
+ return PredEdgeIterator (m_begin);
255
271
}
256
272
257
- iterator end () const
273
+ PredEdgeIterator end () const
258
274
{
259
- return iterator (nullptr );
275
+ return PredEdgeIterator (nullptr );
260
276
}
261
277
};
262
278
@@ -271,30 +287,16 @@ class PredBlockList
271
287
FlowEdge* m_begin;
272
288
273
289
// Forward iterator for the predecessor edges linked list, yielding the predecessor block, not the edge.
274
- // The caller can't make changes to the preds list when using this.
275
290
//
276
- class iterator
291
+ class PredBlockIterator : public BasePredIterator <allowEdits>
277
292
{
278
- FlowEdge* m_pred;
279
-
280
- // When allowEdits=false, try to guard against the user of the iterator from modifying the predecessor list
281
- // being traversed: cache the edge we think should be next, then check it when we actually do the `++`
282
- // operation. This is a bit conservative, but attempts to protect against callers assuming too much about
283
- // this iterator implementation.
284
- // When allowEdits=true, m_next is always used to update m_pred, so changes to m_pred don't break the iterator.
285
- FlowEdge* m_next;
286
-
287
293
public:
288
- iterator (FlowEdge* pred);
289
-
290
- BasicBlock* operator *() const ;
291
-
292
- iterator& operator ++();
293
-
294
- bool operator !=(const iterator& i) const
294
+ PredBlockIterator (FlowEdge* pred)
295
+ : BasePredIterator<allowEdits>(pred)
295
296
{
296
- return m_pred != i.m_pred ;
297
297
}
298
+
299
+ BasicBlock* operator *() const ;
298
300
};
299
301
300
302
public:
@@ -303,14 +305,14 @@ class PredBlockList
303
305
{
304
306
}
305
307
306
- iterator begin () const
308
+ PredBlockIterator begin () const
307
309
{
308
- return iterator (m_begin);
310
+ return PredBlockIterator (m_begin);
309
311
}
310
312
311
- iterator end () const
313
+ PredBlockIterator end () const
312
314
{
313
- return iterator (nullptr );
315
+ return PredBlockIterator (nullptr );
314
316
}
315
317
};
316
318
@@ -1536,9 +1538,18 @@ struct BasicBlock : private LIR::Range
1536
1538
// PredEdges: convenience method for enabling range-based `for` iteration over predecessor edges, e.g.:
1537
1539
// for (FlowEdge* const edge : block->PredEdges()) ...
1538
1540
//
1539
- PredEdgeList PredEdges () const
1541
+ PredEdgeList< false > PredEdges () const
1540
1542
{
1541
- return PredEdgeList (bbPreds);
1543
+ return PredEdgeList<false >(bbPreds);
1544
+ }
1545
+
1546
+ // PredEdgesEditing: convenience method for enabling range-based `for` iteration over predecessor edges, e.g.:
1547
+ // for (FlowEdge* const edge : block->PredEdges()) ...
1548
+ // This iterator tolerates modifications to bbPreds.
1549
+ //
1550
+ PredEdgeList<true > PredEdgesEditing () const
1551
+ {
1552
+ return PredEdgeList<true >(bbPreds);
1542
1553
}
1543
1554
1544
1555
// PredBlocks: convenience method for enabling range-based `for` iteration over predecessor blocks, e.g.:
@@ -2424,30 +2435,8 @@ inline BasicBlock* BBArrayIterator::operator*() const
2424
2435
2425
2436
// Pred list iterator implementations (that are required to be defined after the declaration of BasicBlock and FlowEdge)
2426
2437
2427
- inline PredEdgeList::iterator::iterator (FlowEdge* pred)
2428
- : m_pred(pred)
2429
- {
2430
- #ifdef DEBUG
2431
- m_next = (m_pred == nullptr ) ? nullptr : m_pred->getNextPredEdge ();
2432
- #endif
2433
- }
2434
-
2435
- inline PredEdgeList::iterator& PredEdgeList::iterator::operator ++()
2436
- {
2437
- FlowEdge* next = m_pred->getNextPredEdge ();
2438
-
2439
- #ifdef DEBUG
2440
- // Check that the next block is the one we expect to see.
2441
- assert (next == m_next);
2442
- m_next = (next == nullptr ) ? nullptr : next->getNextPredEdge ();
2443
- #endif // DEBUG
2444
-
2445
- m_pred = next;
2446
- return *this ;
2447
- }
2448
-
2449
2438
template <bool allowEdits>
2450
- inline PredBlockList <allowEdits>::iterator::iterator (FlowEdge* pred)
2439
+ inline BasePredIterator <allowEdits>::BasePredIterator (FlowEdge* pred)
2451
2440
: m_pred(pred)
2452
2441
{
2453
2442
bool initNextPointer = allowEdits;
@@ -2459,13 +2448,7 @@ inline PredBlockList<allowEdits>::iterator::iterator(FlowEdge* pred)
2459
2448
}
2460
2449
2461
2450
template <bool allowEdits>
2462
- inline BasicBlock* PredBlockList<allowEdits>::iterator::operator *() const
2463
- {
2464
- return m_pred->getSourceBlock ();
2465
- }
2466
-
2467
- template <bool allowEdits>
2468
- inline typename PredBlockList<allowEdits>::iterator& PredBlockList<allowEdits>::iterator::operator ++()
2451
+ inline BasePredIterator<allowEdits>& BasePredIterator<allowEdits>::operator ++()
2469
2452
{
2470
2453
if (allowEdits)
2471
2454
{
@@ -2477,18 +2460,22 @@ inline typename PredBlockList<allowEdits>::iterator& PredBlockList<allowEdits>::
2477
2460
{
2478
2461
FlowEdge* next = m_pred->getNextPredEdge ();
2479
2462
2480
- #ifdef DEBUG
2481
2463
// If allowEdits=false, check that the next block is the one we expect to see.
2482
2464
assert (next == m_next);
2483
- m_next = (m_next == nullptr ) ? nullptr : m_next->getNextPredEdge ();
2484
- #endif // DEBUG
2465
+ INDEBUG (m_next = (m_next == nullptr ) ? nullptr : m_next->getNextPredEdge ());
2485
2466
2486
2467
m_pred = next;
2487
2468
}
2488
2469
2489
2470
return *this ;
2490
2471
}
2491
2472
2473
+ template <bool allowEdits>
2474
+ inline BasicBlock* PredBlockList<allowEdits>::PredBlockIterator::operator *() const
2475
+ {
2476
+ return this ->m_pred ->getSourceBlock ();
2477
+ }
2478
+
2492
2479
/* ****************************************************************************
2493
2480
*
2494
2481
* The following call-backs supplied by the client; it's used by the code
0 commit comments