44
44
#include " swift/SIL/SILInstruction.h"
45
45
#include " llvm/ADT/DenseMap.h"
46
46
47
+ // ===----------------------------------------------------------------------===//
48
+ // MARK: General Helpers
49
+ // ===----------------------------------------------------------------------===//
50
+
47
51
namespace swift {
48
52
49
53
// / Get the base address of a formal access by stripping access markers and
@@ -103,6 +107,14 @@ inline bool accessKindMayConflict(SILAccessKind a, SILAccessKind b) {
103
107
return !(a == SILAccessKind::Read && b == SILAccessKind::Read);
104
108
}
105
109
110
+ } // end namespace swift
111
+
112
+ // ===----------------------------------------------------------------------===//
113
+ // MARK: AccessedStorage
114
+ // ===----------------------------------------------------------------------===//
115
+
116
+ namespace swift {
117
+
106
118
// / Represents the identity of a storage object being accessed.
107
119
// /
108
120
// / AccessedStorage is carefully designed to solve three problems:
@@ -406,24 +418,23 @@ class AccessedStorage {
406
418
bool operator ==(const AccessedStorage &) const = delete ;
407
419
bool operator !=(const AccessedStorage &) const = delete ;
408
420
};
421
+
409
422
} // end namespace swift
410
423
411
424
namespace llvm {
412
-
413
425
// / Enable using AccessedStorage as a key in DenseMap.
414
426
// / Do *not* include any extra pass data in key equality.
415
427
template <> struct DenseMapInfo <swift::AccessedStorage> {
416
428
static swift::AccessedStorage getEmptyKey () {
417
429
return swift::AccessedStorage (swift::SILValue::getFromOpaqueValue (
418
- llvm::DenseMapInfo<void *>::getEmptyKey ()),
419
- swift::AccessedStorage::Unidentified);
430
+ llvm::DenseMapInfo<void *>::getEmptyKey ()),
431
+ swift::AccessedStorage::Unidentified);
420
432
}
421
433
422
434
static swift::AccessedStorage getTombstoneKey () {
423
- return swift::AccessedStorage (
424
- swift::SILValue::getFromOpaqueValue (
425
- llvm::DenseMapInfo<void *>::getTombstoneKey ()),
426
- swift::AccessedStorage::Unidentified);
435
+ return swift::AccessedStorage (swift::SILValue::getFromOpaqueValue (
436
+ llvm::DenseMapInfo<void *>::getTombstoneKey ()),
437
+ swift::AccessedStorage::Unidentified);
427
438
}
428
439
429
440
static unsigned getHashValue (swift::AccessedStorage storage) {
@@ -450,63 +461,10 @@ template <> struct DenseMapInfo<swift::AccessedStorage> {
450
461
return LHS.hasIdenticalBase (RHS);
451
462
}
452
463
};
453
-
454
- } // end namespace llvm
464
+ } // namespace llvm
455
465
456
466
namespace swift {
457
467
458
- // / Abstract CRTP class for a visitor passed to \c visitAccessUseDefChain.
459
- template <typename Impl, typename Result = void >
460
- class AccessUseDefChainVisitor {
461
- protected:
462
- Impl &asImpl () {
463
- return static_cast <Impl&>(*this );
464
- }
465
- public:
466
- // Subclasses can provide a method for any identified access base:
467
- // Result visitBase(SILValue base, AccessedStorage::Kind kind);
468
-
469
- // Visitors for specific identified access kinds. These default to calling out
470
- // to visitIdentified.
471
-
472
- Result visitClassAccess (RefElementAddrInst *field) {
473
- return asImpl ().visitBase (field, AccessedStorage::Class);
474
- }
475
- Result visitArgumentAccess (SILFunctionArgument *arg) {
476
- return asImpl ().visitBase (arg, AccessedStorage::Argument);
477
- }
478
- Result visitBoxAccess (AllocBoxInst *box) {
479
- return asImpl ().visitBase (box, AccessedStorage::Box);
480
- }
481
- // / The argument may be either a GlobalAddrInst or the ApplyInst for a global accessor function.
482
- Result visitGlobalAccess (SILValue global) {
483
- return asImpl ().visitBase (global, AccessedStorage::Global);
484
- }
485
- Result visitYieldAccess (BeginApplyResult *yield) {
486
- return asImpl ().visitBase (yield, AccessedStorage::Yield);
487
- }
488
- Result visitStackAccess (AllocStackInst *stack) {
489
- return asImpl ().visitBase (stack, AccessedStorage::Stack);
490
- }
491
- Result visitNestedAccess (BeginAccessInst *access) {
492
- return asImpl ().visitBase (access, AccessedStorage::Nested);
493
- }
494
-
495
- // Visitors for unidentified base values.
496
-
497
- Result visitUnidentified (SILValue base) {
498
- return asImpl ().visitBase (base, AccessedStorage::Unidentified);
499
- }
500
-
501
- // Subclasses must provide implementations to visit non-access bases
502
- // and phi arguments, and for incomplete projections from the access:
503
- // void visitNonAccess(SILValue base);
504
- // void visitPhi(SILPhiArgument *phi);
505
- // void visitIncomplete(SILValue projectedAddr, SILValue parentAddr);
506
-
507
- Result visit (SILValue sourceAddr);
508
- };
509
-
510
468
// / Given an address accessed by an instruction that reads or modifies
511
469
// / memory, return an AccessedStorage object that identifies the formal access.
512
470
// /
@@ -534,6 +492,14 @@ AccessedStorage findAccessedStorage(SILValue sourceAddr);
534
492
// / access has Unsafe enforcement.
535
493
AccessedStorage findAccessedStorageNonNested (SILValue sourceAddr);
536
494
495
+ } // end namespace swift
496
+
497
+ // ===----------------------------------------------------------------------===//
498
+ // MARK: Helper API
499
+ // ===----------------------------------------------------------------------===//
500
+
501
+ namespace swift {
502
+
537
503
// / Return true if the given address operand is used by a memory operation that
538
504
// / initializes the memory at that address, implying that the previous value is
539
505
// / uninitialized.
@@ -550,6 +516,24 @@ bool memInstMustInitialize(Operand *memOper);
550
516
bool isSingleInitAllocStack (AllocStackInst *asi,
551
517
SmallVectorImpl<Operand *> &destroyingUses);
552
518
519
+ // / Return true if the given address value is produced by a special address
520
+ // / producer that is only used for local initialization, not formal access.
521
+ bool isAddressForLocalInitOnly (SILValue sourceAddr);
522
+
523
+ // / Return true if the given apply invokes a global addressor defined in another
524
+ // / module.
525
+ bool isExternalGlobalAddressor (ApplyInst *AI);
526
+
527
+ // / Return true if the given StructExtractInst extracts the RawPointer from
528
+ // / Unsafe[Mutable]Pointer.
529
+ bool isUnsafePointerExtraction (StructExtractInst *SEI);
530
+
531
+ // / Given a block argument address base, check if it is actually a box projected
532
+ // / from a switch_enum. This is a valid pattern at any SIL stage resulting in a
533
+ // / block-type phi. In later SIL stages, the optimizer may form address-type
534
+ // / phis, causing this assert if called on those cases.
535
+ void checkSwitchEnumBlockArg (SILPhiArgument *arg);
536
+
553
537
// / Return true if the given address producer may be the source of a formal
554
538
// / access (a read or write of a potentially aliased, user visible variable).
555
539
// /
@@ -560,17 +544,14 @@ bool isSingleInitAllocStack(AllocStackInst *asi,
560
544
// / storage = findAccessedStorage(address)
561
545
// / needsAccessMarker = storage && isPossibleFormalAccessBase(storage)
562
546
// /
563
- // / Warning: This is only valid for SIL with well-formed accessed . For example,
547
+ // / Warning: This is only valid for SIL with well-formed accesses . For example,
564
548
// / it will not handle address-type phis. Optimization passes after
565
549
// / DiagnoseStaticExclusivity may violate these assumptions.
566
- bool isPossibleFormalAccessBase (const AccessedStorage &storage, SILFunction *F);
567
-
568
- // / Visit each address accessed by the given memory operation.
569
550
// /
570
- // / This only visits instructions that modify memory in some user-visible way,
571
- // / which could be considered part of a formal access.
572
- void visitAccessedAddress (SILInstruction *I,
573
- llvm::function_ref< void (Operand *)> visitor );
551
+ // / This is not a member of AccessedStorage because it only makes sense to use
552
+ // / in SILGen before access markers are emitted, or when verifying access
553
+ // / markers.
554
+ bool isPossibleFormalAccessBase ( const AccessedStorage &storage, SILFunction *F );
574
555
575
556
// / Perform a RAUW operation on begin_access with it's own source operand.
576
557
// / Then erase the begin_access and all associated end_access instructions.
@@ -580,20 +561,65 @@ void visitAccessedAddress(SILInstruction *I,
580
561
// / instruction following this begin_access was not also erased.
581
562
SILBasicBlock::iterator removeBeginAccess (BeginAccessInst *beginAccess);
582
563
583
- // / Return true if the given address value is produced by a special address
584
- // / producer that is only used for local initialization, not formal access.
585
- bool isAddressForLocalInitOnly (SILValue sourceAddr);
586
- // / Return true if the given apply invokes a global addressor defined in another
587
- // / module.
588
- bool isExternalGlobalAddressor (ApplyInst *AI);
589
- // / Return true if the given StructExtractInst extracts the RawPointer from
590
- // / Unsafe[Mutable]Pointer.
591
- bool isUnsafePointerExtraction (StructExtractInst *SEI);
592
- // / Given a block argument address base, check if it is actually a box projected
593
- // / from a switch_enum. This is a valid pattern at any SIL stage resulting in a
594
- // / block-type phi. In later SIL stages, the optimizer may form address-type
595
- // / phis, causing this assert if called on those cases.
596
- void checkSwitchEnumBlockArg (SILPhiArgument *arg);
564
+ } // end namespace swift
565
+
566
+ // ===----------------------------------------------------------------------===//
567
+ // MARK: AccessUseDefChainVisitor
568
+ // ===----------------------------------------------------------------------===//
569
+
570
+ namespace swift {
571
+
572
+ // / Abstract CRTP class for a visitor passed to \c visitAccessUseDefChain.
573
+ template <typename Impl, typename Result = void >
574
+ class AccessUseDefChainVisitor {
575
+ protected:
576
+ Impl &asImpl () { return static_cast <Impl &>(*this ); }
577
+
578
+ public:
579
+ // Subclasses can provide a method for any identified access base:
580
+ // Result visitBase(SILValue base, AccessedStorage::Kind kind);
581
+
582
+ // Visitors for specific identified access kinds. These default to calling out
583
+ // to visitIdentified.
584
+
585
+ Result visitClassAccess (RefElementAddrInst *field) {
586
+ return asImpl ().visitBase (field, AccessedStorage::Class);
587
+ }
588
+ Result visitArgumentAccess (SILFunctionArgument *arg) {
589
+ return asImpl ().visitBase (arg, AccessedStorage::Argument);
590
+ }
591
+ Result visitBoxAccess (AllocBoxInst *box) {
592
+ return asImpl ().visitBase (box, AccessedStorage::Box);
593
+ }
594
+ // / The argument may be either a GlobalAddrInst or the ApplyInst for a global
595
+ // / accessor function.
596
+ Result visitGlobalAccess (SILValue global) {
597
+ return asImpl ().visitBase (global, AccessedStorage::Global);
598
+ }
599
+ Result visitYieldAccess (BeginApplyResult *yield) {
600
+ return asImpl ().visitBase (yield, AccessedStorage::Yield);
601
+ }
602
+ Result visitStackAccess (AllocStackInst *stack) {
603
+ return asImpl ().visitBase (stack, AccessedStorage::Stack);
604
+ }
605
+ Result visitNestedAccess (BeginAccessInst *access) {
606
+ return asImpl ().visitBase (access, AccessedStorage::Nested);
607
+ }
608
+
609
+ // Visitors for unidentified base values.
610
+
611
+ Result visitUnidentified (SILValue base) {
612
+ return asImpl ().visitBase (base, AccessedStorage::Unidentified);
613
+ }
614
+
615
+ // Subclasses must provide implementations to visit non-access bases
616
+ // and phi arguments, and for incomplete projections from the access:
617
+ // void visitNonAccess(SILValue base);
618
+ // void visitPhi(SILPhiArgument *phi);
619
+ // void visitIncomplete(SILValue projectedAddr, SILValue parentAddr);
620
+
621
+ Result visit (SILValue sourceAddr);
622
+ };
597
623
598
624
template <typename Impl, typename Result>
599
625
Result AccessUseDefChainVisitor<Impl, Result>::visit(SILValue sourceAddr) {
@@ -727,11 +753,12 @@ Result AccessUseDefChainVisitor<Impl, Result>::visit(SILValue sourceAddr) {
727
753
return asImpl ().visitIncomplete (sourceAddr,
728
754
cast<SingleValueInstruction>(sourceAddr)->getOperand (0 ));
729
755
730
- // Access to a Builtin.RawPointer. Treat this like the inductive cases
731
- // above because some RawPointers originate from identified locations. See
732
- // the special case for global addressors, which return RawPointer,
733
- // above. AddressToPointer is also handled because it results from inlining a
734
- // global addressor without folding the AddressToPointer->PointerToAddress.
756
+ // Access to a Builtin.RawPointer. Treat this like the inductive cases above
757
+ // because some RawPointers originate from identified locations. See the
758
+ // special case for global addressors, which return RawPointer,
759
+ // above. AddressToPointer is also handled because it results from inlining
760
+ // a global addressor without folding the
761
+ // AddressToPointer->PointerToAddress.
735
762
//
736
763
// If the inductive search does not find a valid addressor, it will
737
764
// eventually reach the default case that returns in invalid location. This
@@ -768,4 +795,19 @@ Result AccessUseDefChainVisitor<Impl, Result>::visit(SILValue sourceAddr) {
768
795
769
796
} // end namespace swift
770
797
798
+ // ===----------------------------------------------------------------------===//
799
+ // MARK: Verification
800
+ // ===----------------------------------------------------------------------===//
801
+
802
+ namespace swift {
803
+
804
+ // / Visit each address accessed by the given memory operation.
805
+ // /
806
+ // / This only visits instructions that modify memory in some user-visible way,
807
+ // / which could be considered part of a formal access.
808
+ void visitAccessedAddress (SILInstruction *I,
809
+ llvm::function_ref<void (Operand *)> visitor);
810
+
811
+ } // end namespace swift
812
+
771
813
#endif
0 commit comments