10
10
//
11
11
// ===----------------------------------------------------------------------===//
12
12
13
+ #include " swift/Basic/LLVM.h"
13
14
#include " swift/SIL/SILArgument.h"
14
15
#include " swift/SIL/SILInstruction.h"
15
16
#include " swift/SIL/SILValue.h"
16
17
#include " llvm/ADT/DenseMap.h"
18
+ #include " llvm/ADT/STLExtras.h"
17
19
18
20
namespace swift {
19
21
@@ -217,6 +219,63 @@ class ValueStorageMap {
217
219
SWIFT_ASSERT_ONLY_DECL (bool stableStorage = false );
218
220
219
221
public:
222
+ class ProjectionIterator {
223
+ public:
224
+ using This = ProjectionIterator;
225
+ using iterator_category = std::forward_iterator_tag;
226
+ using value_type = ValueStoragePair const *;
227
+ using difference_type = std::ptrdiff_t ;
228
+ using pointer = value_type *;
229
+ using reference = value_type &;
230
+
231
+ protected:
232
+ value_type Cur;
233
+ ValueStorageMap const ⤅
234
+
235
+ public:
236
+ explicit ProjectionIterator (value_type cur, ValueStorageMap const &map)
237
+ : Cur(cur), Map(map) {}
238
+ ValueStoragePair const *operator ->() const { return Cur; }
239
+ ValueStoragePair const *operator *() const { return Cur; }
240
+
241
+ ValueStorage const &getStorage () const { return Cur->storage ; }
242
+ SILValue getValue () const { return Cur->value ; }
243
+ This &operator ++() {
244
+ assert (Cur && " incrementing past end()!" );
245
+ if (Cur->storage .isProjection ())
246
+ Cur = &Map.getProjectedStorage (Cur->storage );
247
+ else
248
+ Cur = nullptr ;
249
+ return *this ;
250
+ }
251
+
252
+ This operator ++(int unused) {
253
+ This copy = *this ;
254
+ ++*this ;
255
+ return copy;
256
+ }
257
+
258
+ friend bool operator ==(This lhs, This rhs) { return lhs.Cur == rhs.Cur ; }
259
+ friend bool operator !=(This lhs, This rhs) { return !(lhs == rhs); }
260
+ };
261
+
262
+ ProjectionIterator projection_begin (SILValue value) const {
263
+ return ProjectionIterator (&valueVector[getOrdinal (value)], *this );
264
+ }
265
+ ProjectionIterator projection_end () const {
266
+ return ProjectionIterator (nullptr , *this );
267
+ }
268
+ // / Returns projections of the specified value from the inside out, starting
269
+ // / from the projection for the value and walking outwards to its storage
270
+ // / root.
271
+ iterator_range<ProjectionIterator> getProjections (SILValue value) const {
272
+ if (!contains (value))
273
+ return {projection_end (), projection_end ()};
274
+ return {projection_begin (value), projection_end ()};
275
+ }
276
+
277
+ friend class ProjectionIterator ;
278
+
220
279
bool empty () const { return valueVector.empty (); }
221
280
222
281
void clear () {
@@ -276,35 +335,33 @@ class ValueStorageMap {
276
335
return valueVector[storage.projectedStorageID ];
277
336
}
278
337
279
- // / Return the non-projection storage that the given storage ultimately refers
280
- // / to by following all projections. After allocation, this storage always has
281
- // / a valid address.
282
- const ValueStorage &getBaseStorage (const ValueStorage &storage) {
283
- if (storage.isDefProjection || storage.isUseProjection )
284
- return getBaseStorage (getProjectedStorage (storage).storage );
285
-
286
- return storage;
287
- }
288
-
289
338
// / Return the non-projection storage that the given storage ultimately refers
290
339
// / to by following all projections.
291
340
const ValueStorage &getBaseStorage (SILValue value) {
292
- return getBaseStorage (getStorage (value));
341
+ ValueStorage const *last = nullptr ;
342
+ for (auto *pair : getProjections (value)) {
343
+ last = &pair->storage ;
344
+ }
345
+ return *last;
293
346
}
294
347
295
348
// / Return the non-projection storage that this storage refers to. If this
296
349
// / storage holds an Enum or any intermediate storage that projects into this
297
350
// / storage holds an Enum, then return nullptr.
298
- const ValueStorage *getNonEnumBaseStorage (const ValueStorage &storage) {
299
- if (storage.initializesEnum )
300
- return nullptr ;
301
-
302
- if (storage.isUseProjection ) {
303
- auto &storageAndValue = getProjectedStorage (storage);
304
- return getNonEnumBaseStorage (storageAndValue.storage );
351
+ const ValueStorage *getNonEnumBaseStorage (SILValue value) {
352
+ for (auto *pair : getProjections (value)) {
353
+ auto const &storage = pair->storage ;
354
+ if (storage.initializesEnum )
355
+ return nullptr ;
356
+
357
+ if (storage.isUseProjection ) {
358
+ continue ;
359
+ }
360
+ assert (!storage.isDefProjection &&
361
+ " def projections should not reach here" );
362
+ return &storage;
305
363
}
306
- assert (!storage.isDefProjection && " def projections should not reach here" );
307
- return &storage;
364
+ llvm_unreachable (" found no non-projection storage!?" );
308
365
}
309
366
310
367
// / Return the non-projection storage that this storage refers to, or nullptr
@@ -313,7 +370,7 @@ class ValueStorageMap {
313
370
if (allowInitEnum)
314
371
return &getBaseStorage (value);
315
372
316
- return getNonEnumBaseStorage (getStorage ( value) );
373
+ return getNonEnumBaseStorage (value);
317
374
}
318
375
319
376
void setStorageAddress (SILValue value, SILValue addr) {
0 commit comments