Skip to content

Commit 94b0cae

Browse files
authored
Merge pull request #65353 from gottesmm/pr-7fddccd1df47d4c57c27121727562d691b9f2397
[move-only] A group of batched changes
2 parents debb455 + 9c8d224 commit 94b0cae

40 files changed

+4198
-737
lines changed

include/swift/AST/DiagnosticsSIL.def

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,17 @@ ERROR(exclusivity_access_required_unknown_decl,none,
8888
"%select{initialization|read|modification|deinitialization}0 requires "
8989
"exclusive access; consider copying to a local variable", (unsigned))
9090

91+
ERROR(exclusivity_access_required_moveonly,none,
92+
"overlapping accesses to %0, but "
93+
"%select{initialization|read|modification|deinitialization}1 requires "
94+
"exclusive access",
95+
(StringRef, unsigned))
96+
97+
ERROR(exclusivity_access_required_unknown_decl_moveonly,none,
98+
"overlapping accesses, but "
99+
"%select{initialization|read|modification|deinitialization}0 requires "
100+
"exclusive access", (unsigned))
101+
91102
NOTE(exclusivity_conflicting_access,none,
92103
"conflicting access is here", ())
93104

include/swift/AST/SemanticAttrs.def

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,21 @@ SEMANTICS_ATTR(LIFETIMEMANAGEMENT_COPY, "lifetimemanagement.copy")
127127

128128
SEMANTICS_ATTR(NO_PERFORMANCE_ANALYSIS, "no_performance_analysis")
129129

130-
// A flag used to turn off moveonly diagnostics on functions that allocbox to
131-
// stack specialized.
130+
// A flag used to turn off moveonly diagnostics on a function due to an earlier
131+
// pass that ran.
132+
//
133+
// DISCUSSION: This is used in a few situations:
134+
//
135+
// 1. When allocbox to stack specializes a function, we do not want to emit move
136+
// errors twice, once on the specialized and once on the original
137+
// function. Instead, we put this on the original function.
138+
//
139+
// 2. If we emit a diagnose invalid escaping captures error due to an inout
140+
// being escaped into an escaping closure, we do not want to emit move errors in
141+
// the closure. This is because SILGen today assumes that we will error in such
142+
// cases and thus does not emit markers in said function for the inout. This
143+
// then causes us to emit spurious "found a copy of a noncopyable value" errors
144+
// that may cause the user to think there is a bug in the compiler.
132145
SEMANTICS_ATTR(NO_MOVEONLY_DIAGNOSTICS, "sil.optimizer.moveonly.diagnostic.ignore")
133146

134147
#undef SEMANTICS_ATTR

include/swift/Basic/NoDiscard.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//===--- NoDiscard.h ------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_BASIC_NODISCARD_H
14+
#define SWIFT_BASIC_NODISCARD_H
15+
16+
#if __cplusplus > 201402l && __has_cpp_attribute(nodiscard)
17+
#define SWIFT_NODISCARD [[nodiscard]]
18+
#elif __has_cpp_attribute(clang::warn_unused_result)
19+
#define SWIFT_NODISCARD [[clang::warn_unused_result]]
20+
#else
21+
#define SWIFT_NODISCARD
22+
#endif
23+
24+
#endif

include/swift/SIL/AddressUseKind.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//===--- AddressUseKind.h -------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_SIL_ADDRESSUSEKIND_H
14+
#define SWIFT_SIL_ADDRESSUSEKIND_H
15+
16+
namespace swift {
17+
18+
enum class AddressUseKind { NonEscaping, PointerEscape, Unknown };
19+
20+
inline AddressUseKind meet(AddressUseKind lhs, AddressUseKind rhs) {
21+
return (lhs > rhs) ? lhs : rhs;
22+
}
23+
24+
} // namespace swift
25+
26+
#endif

include/swift/SIL/AddressWalker.h

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//===--- AddressWalker.h --------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
///
13+
/// \file
14+
///
15+
/// This header defines a walker for SIL addresses that is guaranteed by the
16+
/// language to be able to traverse the SIL from an address def to all of its
17+
/// transitive uses. This is validated by the SIL optimizer.
18+
///
19+
//===----------------------------------------------------------------------===//
20+
21+
#ifndef SWIFT_SIL_ADDRESSWALKER_H
22+
#define SWIFT_SIL_ADDRESSWALKER_H
23+
24+
#include "swift/SIL/AddressUseKind.h"
25+
#include "swift/SIL/SILValue.h"
26+
27+
namespace swift {
28+
29+
/// A state structure for findTransitiveUsesForAddress. Intended to be only used
30+
/// a single time. Please always use a new one for every call to
31+
/// findTransitiveUsesForAddress.
32+
///
33+
/// Validated by the SIL verifier as always being able to visit all addresses
34+
/// derived from alloc_stack, ref_element_addr, project_box, ref_tail_addr and
35+
/// all other address roots.
36+
class TransitiveAddressWalker {
37+
/// Whether we could tell if this address use didn't escape, did have a
38+
/// pointer escape, or unknown if we failed to understand something.
39+
AddressUseKind result = AddressUseKind::NonEscaping;
40+
41+
unsigned didInvalidate = false;
42+
43+
public:
44+
virtual ~TransitiveAddressWalker() {}
45+
46+
protected:
47+
/// Customization point for visiting uses. Returns true if we should continue
48+
/// visiting.
49+
///
50+
/// NOTE: Do not call this directly from within
51+
/// findTransitiveUsesForAddress. Please call callVisitUse. This is intended
52+
/// just for subclasses to override.
53+
virtual bool visitUse(Operand *use) { return true; }
54+
55+
virtual void onError(Operand *use) {}
56+
57+
void meet(AddressUseKind other) {
58+
assert(!didInvalidate);
59+
result = swift::meet(result, other);
60+
}
61+
62+
private:
63+
/// Shim that actually calls visitUse and changes early exit.
64+
void callVisitUse(Operand *use) {
65+
assert(!didInvalidate);
66+
if (!visitUse(use))
67+
result = AddressUseKind::Unknown;
68+
}
69+
70+
public:
71+
AddressUseKind walk(SILValue address) &&;
72+
};
73+
74+
/// The algorithm that is used to determine what the verifier will consider to
75+
/// be transitive uses of the given address. Used to implement \see
76+
/// findTransitiveUses.
77+
///
78+
/// Returns \p AccessUseKind::Unknown on error.
79+
AddressUseKind findTransitiveUsesForAddress(SILValue address,
80+
TransitiveAddressWalker &visitor);
81+
82+
} // namespace swift
83+
84+
#endif

include/swift/SIL/OwnershipUtils.h

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
#include "swift/Basic/Debug.h"
1717
#include "swift/Basic/LLVM.h"
18+
#include "swift/Basic/NoDiscard.h"
19+
#include "swift/SIL/AddressWalker.h"
1820
#include "swift/SIL/MemAccessUtils.h"
1921
#include "swift/SIL/SILArgument.h"
2022
#include "swift/SIL/SILBasicBlock.h"
@@ -753,19 +755,65 @@ bool getAllBorrowIntroducingValues(SILValue value,
753755
/// introducer, then we return a .some(BorrowScopeIntroducingValue).
754756
BorrowedValue getSingleBorrowIntroducingValue(SILValue inputValue);
755757

756-
enum class AddressUseKind { NonEscaping, PointerEscape, Unknown };
757-
758-
inline AddressUseKind meet(AddressUseKind lhs, AddressUseKind rhs) {
759-
return (lhs > rhs) ? lhs : rhs;
760-
}
761-
762758
/// The algorithm that is used to determine what the verifier will consider to
763759
/// be transitive uses of the given address. Used to implement \see
764760
/// findTransitiveUses.
765-
AddressUseKind
766-
findTransitiveUsesForAddress(SILValue address,
767-
SmallVectorImpl<Operand *> *foundUses = nullptr,
768-
std::function<void(Operand *)> *onError = nullptr);
761+
///
762+
/// NOTE: Rather than return load_borrow as uses, this returns all of the
763+
/// transitive uses of the load_borrow as uses. This is important when working
764+
/// with this in OSSA. If one wishes to avoid this behavior, call find
765+
/// transitive uses for address with ones own visitor.
766+
inline AddressUseKind findTransitiveUsesForAddress(
767+
SILValue address, SmallVectorImpl<Operand *> *foundUses = nullptr,
768+
std::function<void(Operand *)> *onError = nullptr) {
769+
// This is a version of TransitiveUseVisitor that visits inner transitive
770+
// guaranteed uses to determine if a load_borrow is an escape in OSSA. This
771+
// is OSSA specific behavior and we should probably create a different API
772+
// for that. But for now, this lets this APIs users stay the same.
773+
struct BasicTransitiveAddressVisitor final : TransitiveAddressWalker {
774+
SmallVectorImpl<Operand *> *foundUses;
775+
std::function<void(Operand *)> *onErrorFunc;
776+
777+
BasicTransitiveAddressVisitor(SmallVectorImpl<Operand *> *foundUses,
778+
std::function<void(Operand *)> *onErrorFunc)
779+
: foundUses(foundUses), onErrorFunc(onErrorFunc) {}
780+
781+
bool visitUse(Operand *use) override {
782+
if (!foundUses)
783+
return true;
784+
785+
if (auto *lbi = dyn_cast<LoadBorrowInst>(use->getUser())) {
786+
if (!findInnerTransitiveGuaranteedUses(lbi, foundUses)) {
787+
meet(AddressUseKind::PointerEscape);
788+
}
789+
return true;
790+
}
791+
792+
// If we have a begin_apply, we want to use the token results if we have
793+
// any. If it doesn't have any token results, we just make our use the
794+
// begin_apply use itself below.
795+
if (auto *bai = dyn_cast<BeginApplyInst>(use->getUser())) {
796+
if (!bai->getTokenResult()->use_empty()) {
797+
for (auto *use : bai->getTokenResult()->getUses()) {
798+
foundUses->push_back(use);
799+
}
800+
return true;
801+
}
802+
}
803+
804+
foundUses->push_back(use);
805+
return true;
806+
}
807+
808+
void onError(Operand *use) override {
809+
if (onErrorFunc)
810+
(*onErrorFunc)(use);
811+
}
812+
};
813+
814+
BasicTransitiveAddressVisitor visitor(foundUses, onError);
815+
return std::move(visitor).walk(address);
816+
}
769817

770818
class InteriorPointerOperandKind {
771819
public:

include/swift/SILOptimizer/Analysis/AccessSummaryAnalysis.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,12 @@ class AccessSummaryAnalysis : public BottomUpIPAnalysis {
205205
SILModule &M,
206206
TypeExpansionContext context);
207207

208+
/// Returns the type associated with the subpath \p SubPath.
209+
///
210+
/// \p BaseType must be the type of the root of the path.
211+
static SILType getSubPathType(SILType BaseType, const IndexTrieNode *SubPath,
212+
SILModule &M, TypeExpansionContext context);
213+
208214
/// Performs a lexicographic comparison of two subpaths, first by path length
209215
/// and then by index of the last path component. Returns true when lhs
210216
/// is less than rhs.

0 commit comments

Comments
 (0)