@@ -258,47 +258,74 @@ class FindAccessBaseVisitor
258
258
using SuperTy = FindAccessVisitorImpl<FindAccessBaseVisitor>;
259
259
260
260
protected:
261
- Optional<SILValue> base;
261
+ // If the optional baseVal is set, then a result was found. If the SILValue
262
+ // within the optional is invalid, then there are multiple inconsistent base
263
+ // addresses (this may currently happen with RawPointer phis).
264
+ Optional<SILValue> baseVal;
265
+ // If the kind optional is set, then 'baseVal' is a valid
266
+ // AccessBase. 'baseVal' may be a valid SILValue while kind optional has no
267
+ // value if an invalid address producer was detected, via a call to
268
+ // visitNonAccess.
269
+ Optional<AccessBase::Kind> kindVal;
262
270
263
271
public:
264
272
FindAccessBaseVisitor (NestedAccessType nestedAccessTy,
265
273
StorageCastTy storageCastTy)
266
274
: FindAccessVisitorImpl(nestedAccessTy, storageCastTy) {}
267
275
268
276
// Returns the accessed address or an invalid SILValue.
269
- SILValue findBase (SILValue sourceAddr) && {
277
+ SILValue findPossibleBaseAddress (SILValue sourceAddr) && {
270
278
reenterUseDef (sourceAddr);
271
- return base.getValueOr (SILValue ());
279
+ return baseVal.getValueOr (SILValue ());
280
+ }
281
+
282
+ AccessBase findBase (SILValue sourceAddr) && {
283
+ reenterUseDef (sourceAddr);
284
+ if (!baseVal || !kindVal)
285
+ return AccessBase ();
286
+
287
+ return AccessBase (baseVal.getValue (), kindVal.getValue ());
272
288
}
273
289
274
290
void setResult (SILValue foundBase) {
275
- if (!base )
276
- base = foundBase;
277
- else if (base .getValue () != foundBase)
278
- base = SILValue ();
291
+ if (!baseVal )
292
+ baseVal = foundBase;
293
+ else if (baseVal .getValue () != foundBase)
294
+ baseVal = SILValue ();
279
295
}
280
296
281
297
// MARK: AccessPhiVisitor::UseDefVisitor implementation.
282
298
283
- bool isResultValid () const { return base && bool (base.getValue ()); }
299
+ // Keep going as long as baseVal is valid regardless of kindVal.
300
+ bool isResultValid () const { return baseVal && bool (baseVal.getValue ()); }
284
301
285
- void invalidateResult () { base = SILValue (); }
302
+ void invalidateResult () {
303
+ baseVal = SILValue ();
304
+ kindVal = None;
305
+ }
286
306
287
- Optional<SILValue> saveResult () const { return base ; }
307
+ Optional<SILValue> saveResult () const { return baseVal ; }
288
308
289
- void restoreResult (Optional<SILValue> result) { base = result; }
309
+ void restoreResult (Optional<SILValue> result) { baseVal = result; }
290
310
291
311
void addUnknownOffset () { return ; }
292
312
293
313
// MARK: visitor implementation.
294
314
295
315
SILValue visitBase (SILValue base, AccessStorage::Kind kind) {
296
316
setResult (base);
317
+ if (!baseVal.getValue ()) {
318
+ kindVal = None;
319
+ } else {
320
+ assert (!kindVal || kindVal.getValue () == kind);
321
+ kindVal = kind;
322
+ }
297
323
return SILValue ();
298
324
}
299
325
300
326
SILValue visitNonAccess (SILValue value) {
301
327
setResult (value);
328
+ kindVal = None;
302
329
return SILValue ();
303
330
}
304
331
@@ -322,7 +349,7 @@ SILValue swift::getTypedAccessAddress(SILValue address) {
322
349
SILValue accessAddress =
323
350
FindAccessBaseVisitor (NestedAccessType::StopAtAccessBegin,
324
351
StopAtStorageCast)
325
- .findBase (address);
352
+ .findPossibleBaseAddress (address);
326
353
assert (accessAddress->getType ().isAddress ());
327
354
return accessAddress;
328
355
}
@@ -334,14 +361,14 @@ SILValue swift::getAccessScope(SILValue address) {
334
361
assert (address->getType ().isAddress ());
335
362
return FindAccessBaseVisitor (NestedAccessType::StopAtAccessBegin,
336
363
IgnoreStorageCast)
337
- .findBase (address);
364
+ .findPossibleBaseAddress (address);
338
365
}
339
366
340
367
// This is allowed to be called on a non-address pointer type.
341
368
SILValue swift::getAccessBase (SILValue address) {
342
369
return FindAccessBaseVisitor (NestedAccessType::IgnoreAccessBegin,
343
370
IgnoreStorageCast)
344
- .findBase (address);
371
+ .findPossibleBaseAddress (address);
345
372
}
346
373
347
374
static bool isLetForBase (SILValue base) {
@@ -510,6 +537,12 @@ void AccessRepresentation::print(raw_ostream &os) const {
510
537
// MARK: AccessBase
511
538
// ===----------------------------------------------------------------------===//
512
539
540
+ AccessBase AccessBase::compute (SILValue sourceAddress) {
541
+ return FindAccessBaseVisitor (NestedAccessType::IgnoreAccessBegin,
542
+ IgnoreStorageCast)
543
+ .findBase (sourceAddress);
544
+ }
545
+
513
546
AccessBase::AccessBase (SILValue base, Kind kind)
514
547
: AccessRepresentation(base, kind)
515
548
{
@@ -609,6 +642,30 @@ const ValueDecl *AccessBase::getDecl() const {
609
642
}
610
643
}
611
644
645
+ bool AccessBase::hasLocalOwnershipLifetime () const {
646
+ switch (getKind ()) {
647
+ case AccessBase::Argument:
648
+ case AccessBase::Stack:
649
+ case AccessBase::Global:
650
+ return false ;
651
+ case AccessBase::Unidentified:
652
+ // Unidentified storage may be nested within object access, but this is an
653
+ // "escaped pointer", so it is not restricted to the object's borrow scope.
654
+ return false ;
655
+ case AccessBase::Yield:
656
+ // Yielded values have a local apply scope, but they never have the same
657
+ // storage as yielded values from a different scope, so there is no need to
658
+ // consider their local scope during substitution.
659
+ return false ;
660
+ case AccessBase::Box:
661
+ case AccessBase::Class:
662
+ case AccessBase::Tail:
663
+ return getReference ()->getOwnershipKind () != OwnershipKind::None;
664
+ case AccessBase::Nested:
665
+ llvm_unreachable (" unexpected storage" );
666
+ };
667
+ }
668
+
612
669
void AccessBase::print (raw_ostream &os) const {
613
670
AccessRepresentation::print (os);
614
671
switch (getKind ()) {
@@ -675,12 +732,8 @@ namespace {
675
732
// Essentially RC identity where the starting point is already a reference.
676
733
class FindReferenceRoot {
677
734
SmallPtrSet<SILPhiArgument *, 4 > visitedPhis;
678
- bool preserveOwnership;
679
735
680
736
public:
681
- FindReferenceRoot (bool preserveOwnership)
682
- : preserveOwnership(preserveOwnership) {}
683
-
684
737
SILValue findRoot (SILValue ref) && {
685
738
SILValue root = recursiveFindRoot (ref);
686
739
assert (root && " all phi inputs must be reachable" );
@@ -692,14 +745,8 @@ class FindReferenceRoot {
692
745
SILValue recursiveFindRoot (SILValue ref) {
693
746
while (auto *svi = dyn_cast<SingleValueInstruction>(ref)) {
694
747
// If preserveOwnership is true, stop at the first owned root
695
- if (preserveOwnership) {
696
- if (!isIdentityAndOwnershipPreservingRefCast (svi)) {
697
- break ;
698
- }
699
- } else {
700
- if (!isIdentityPreservingRefCast (svi)) {
701
- break ;
702
- }
748
+ if (!isIdentityPreservingRefCast (svi)) {
749
+ break ;
703
750
}
704
751
ref = svi->getOperand (0 );
705
752
};
@@ -735,11 +782,54 @@ class FindReferenceRoot {
735
782
} // end anonymous namespace
736
783
737
784
SILValue swift::findReferenceRoot (SILValue ref) {
738
- return FindReferenceRoot (false /* preserveOwnership */ ).findRoot (ref);
785
+ return FindReferenceRoot ().findRoot (ref);
739
786
}
740
787
788
+ // This does not handle phis because a phis is either a consume or a
789
+ // reborrow. In either case, the phi argument's ownership is independent from
790
+ // the phi itself. The client assumes that the returned root is in the same
791
+ // lifetime or borrow scope of the access.
741
792
SILValue swift::findOwnershipReferenceRoot (SILValue ref) {
742
- return FindReferenceRoot (true /* preserveOwnership*/ ).findRoot (ref);
793
+ while (auto *svi = dyn_cast<SingleValueInstruction>(ref)) {
794
+ if (isIdentityAndOwnershipPreservingRefCast (svi)) {
795
+ ref = svi->getOperand (0 );
796
+ continue ;
797
+ }
798
+ break ;
799
+ }
800
+ return ref;
801
+ }
802
+
803
+ // / Find the first owned aggregate containing the reference, or simply the
804
+ // / reference root if no aggregate is found.
805
+ // /
806
+ // / TODO: Add a component path to a ReferenceRoot abstraction and handle
807
+ // / that within FindReferenceRoot.
808
+ SILValue swift::findOwnershipReferenceAggregate (SILValue ref) {
809
+ SILValue root = ref;
810
+ while (true ) {
811
+ root = findOwnershipReferenceRoot (root);
812
+ if (!root)
813
+ return root;
814
+ if (isa<FirstArgOwnershipForwardingSingleValueInst>(root)
815
+ || isa<OwnershipForwardingConversionInst>(root)
816
+ || isa<OwnershipForwardingSelectEnumInstBase>(root)
817
+ || isa<OwnershipForwardingMultipleValueInstruction>(root)) {
818
+ root = root->getDefiningInstruction ()->getOperand (0 );
819
+ continue ;
820
+ }
821
+ if (auto *arg = dyn_cast<SILArgument>(root)) {
822
+ if (auto *term = arg->getSingleTerminator ()) {
823
+ if (term->isTransformationTerminator ()) {
824
+ assert (OwnershipForwardingTermInst::isa (term));
825
+ root = term->getOperand (0 );
826
+ continue ;
827
+ }
828
+ }
829
+ }
830
+ break ;
831
+ }
832
+ return root;
743
833
}
744
834
745
835
// ===----------------------------------------------------------------------===//
@@ -802,17 +892,6 @@ void AccessStorage::visitRoots(
802
892
}
803
893
}
804
894
805
- bool AccessStorage::isGuaranteedForFunction () const {
806
- if (getKind () == AccessStorage::Argument) {
807
- return getArgument ()->getArgumentConvention ().isGuaranteedConvention ();
808
- }
809
- if (isObjectAccess ()) {
810
- return getRoot ().getOwnershipKind () == OwnershipKind::Guaranteed
811
- && isa<SILFunctionArgument>(getRoot ());
812
- }
813
- return false ;
814
- }
815
-
816
895
const ValueDecl *AccessStorage::getDecl () const {
817
896
switch (getKind ()) {
818
897
case Box:
0 commit comments