Skip to content

Commit 34b0cbc

Browse files
authored
Merge pull request #16237 from davezarzycki/metaprogram_ref_storage_types
[AST] NFC: Enable reference storage type meta-programming
2 parents 3add046 + 057bbb3 commit 34b0cbc

File tree

96 files changed

+3733
-4083
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+3733
-4083
lines changed

include/swift/AST/Attr.def

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,8 @@ TYPE_ATTR(escaping)
5757
TYPE_ATTR(block_storage)
5858
TYPE_ATTR(box)
5959
TYPE_ATTR(dynamic_self)
60-
TYPE_ATTR(sil_unowned)
61-
TYPE_ATTR(sil_unmanaged)
62-
TYPE_ATTR(sil_weak)
60+
#define REF_STORAGE(Name, name, ...) TYPE_ATTR(sil_##name)
61+
#include "swift/AST/ReferenceStorage.def"
6362
TYPE_ATTR(error)
6463
TYPE_ATTR(out)
6564
TYPE_ATTR(in)

include/swift/AST/Attr.h

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -111,19 +111,16 @@ class TypeAttributes {
111111
return getOwnership() != ReferenceOwnership::Strong;
112112
}
113113
ReferenceOwnership getOwnership() const {
114-
if (has(TAK_sil_weak))
115-
return ReferenceOwnership::Weak;
116-
if (has(TAK_sil_unowned))
117-
return ReferenceOwnership::Unowned;
118-
if (has(TAK_sil_unmanaged))
119-
return ReferenceOwnership::Unmanaged;
114+
#define REF_STORAGE(Name, name, ...) \
115+
if (has(TAK_sil_##name)) return ReferenceOwnership::Name;
116+
#include "swift/AST/ReferenceStorage.def"
120117
return ReferenceOwnership::Strong;
121118
}
122119

123120
void clearOwnership() {
124-
clearAttribute(TAK_sil_weak);
125-
clearAttribute(TAK_sil_unowned);
126-
clearAttribute(TAK_sil_unmanaged);
121+
#define REF_STORAGE(Name, name, ...) \
122+
clearAttribute(TAK_sil_##name);
123+
#include "swift/AST/ReferenceStorage.def"
127124
}
128125

129126
bool hasOpenedID() const { return OpenedID.hasValue(); }

include/swift/AST/DiagnosticsParse.def

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -551,12 +551,9 @@ ERROR(sil_invalid_instr_operands,none,
551551
"invalid instruction operands", ())
552552
ERROR(sil_operand_not_address,none,
553553
"%0 operand of '%1' must have address type", (StringRef, StringRef))
554-
ERROR(sil_operand_not_unowned_address,none,
555-
"%0 operand of '%1' must have address of [unowned] type",
556-
(StringRef, StringRef))
557-
ERROR(sil_operand_not_weak_address,none,
558-
"%0 operand of '%1' must have address of [weak] type",
559-
(StringRef, StringRef))
554+
ERROR(sil_operand_not_ref_storage_address,none,
555+
"%0 operand of '%1' must have address of %2 type",
556+
(StringRef, StringRef, ReferenceOwnership))
560557
ERROR(sil_integer_literal_not_integer_type,none,
561558
"integer_literal instruction requires a 'Builtin.Int<n>' type", ())
562559
ERROR(sil_float_literal_not_float_type,none,

include/swift/AST/DiagnosticsSema.def

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3390,10 +3390,12 @@ ERROR(invalid_ownership_protocol_type,none,
33903390
(ReferenceOwnership, Type))
33913391
ERROR(invalid_ownership_with_optional,none,
33923392
"%0 variable cannot have optional type", (ReferenceOwnership))
3393-
ERROR(invalid_weak_ownership_not_optional,none,
3394-
"'weak' variable should have optional type %0", (Type))
3395-
ERROR(invalid_weak_let,none,
3396-
"'weak' must be a mutable variable, because it may change at runtime", ())
3393+
ERROR(invalid_ownership_not_optional,none,
3394+
"%0 variable should have optional type %1",
3395+
(ReferenceOwnership, Type))
3396+
ERROR(invalid_ownership_is_let,none,
3397+
"%0 must be a mutable variable, because it may change at runtime",
3398+
(ReferenceOwnership))
33973399
ERROR(ownership_invalid_in_protocols,none,
33983400
"%0 cannot be applied to a property declaration in a protocol",
33993401
(ReferenceOwnership))

include/swift/AST/Ownership.h

Lines changed: 81 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#define SWIFT_OWNERSHIP_H
2121

2222
#include "swift/Basic/InlineBitfield.h"
23+
#include "llvm/ADT/StringRef.h"
24+
#include "llvm/Support/ErrorHandling.h"
2325
#include "llvm/Support/raw_ostream.h"
2426
#include <stdint.h>
2527

@@ -32,20 +34,85 @@ enum class ReferenceOwnership : uint8_t {
3234
/// \brief a strong reference (the default semantics)
3335
Strong,
3436

35-
/// \brief a 'weak' reference
36-
Weak,
37+
#define REF_STORAGE(Name, ...) Name,
38+
#define REF_STORAGE_RANGE(First, Last) Last_Kind = Last
39+
#include "swift/AST/ReferenceStorage.def"
40+
};
41+
42+
enum : unsigned { NumReferenceOwnershipBits =
43+
countBitsUsed(static_cast<unsigned>(ReferenceOwnership::Last_Kind)) };
44+
45+
static inline llvm::StringRef keywordOf(ReferenceOwnership ownership) {
46+
switch (ownership) {
47+
case ReferenceOwnership::Strong:
48+
assert(false && "not applicable");
49+
case ReferenceOwnership::Weak: return "weak";
50+
case ReferenceOwnership::Unowned: return "unowned";
51+
case ReferenceOwnership::Unmanaged: return "unowned(unsafe)";
52+
}
53+
assert(false && "impossible");
54+
}
3755

38-
/// \brief an 'unowned' reference
39-
Unowned,
56+
static inline llvm::StringRef manglingOf(ReferenceOwnership ownership) {
57+
switch (ownership) {
58+
case ReferenceOwnership::Strong:
59+
assert(false && "not applicable");
60+
case ReferenceOwnership::Weak: return "Xw";
61+
case ReferenceOwnership::Unowned: return "Xo";
62+
case ReferenceOwnership::Unmanaged: return "Xu";
63+
}
64+
assert(false && "impossible");
65+
}
4066

41-
/// \brief an 'unowned(unsafe)' reference
42-
Unmanaged,
67+
static inline bool isLessStrongThan(ReferenceOwnership left,
68+
ReferenceOwnership right) {
69+
auto strengthOf = [] (ReferenceOwnership ownership) -> int {
70+
// A reference can be optimized away if outlived by a stronger reference.
71+
// NOTES:
72+
// 1) Different reference kinds of the same strength are NOT interchangable.
73+
// 2) Stronger than "strong" might include locking, for example.
74+
// 3) Unchecked references must be last to preserve identity comparisons
75+
// until the last checked reference is dead.
76+
// 4) Please keep the switch statement ordered to ease code review.
77+
switch (ownership) {
78+
case ReferenceOwnership::Strong: return 0;
79+
case ReferenceOwnership::Unowned: return -1;
80+
case ReferenceOwnership::Weak: return -1;
81+
#define UNCHECKED_REF_STORAGE(Name, ...) \
82+
case ReferenceOwnership::Name: return INT_MIN;
83+
#include "swift/AST/ReferenceStorage.def"
84+
}
85+
llvm_unreachable("impossible");
86+
};
4387

44-
Last_Kind = Unmanaged
88+
return strengthOf(left) < strengthOf(right);
89+
}
90+
91+
enum class ReferenceOwnershipOptionality : uint8_t {
92+
Disallowed,
93+
Allowed,
94+
AllowedIfImporting,
95+
Required,
96+
97+
Last_Kind = Required
4598
};
99+
enum : unsigned { NumOptionalityBits = countBitsUsed(static_cast<unsigned>(
100+
ReferenceOwnershipOptionality::Last_Kind)) };
46101

47-
enum : unsigned { NumReferenceOwnershipBits =
48-
countBitsUsed(static_cast<unsigned>(ReferenceOwnership::Last_Kind)) };
102+
static inline ReferenceOwnershipOptionality
103+
optionalityOf(ReferenceOwnership ownership) {
104+
switch (ownership) {
105+
case ReferenceOwnership::Strong:
106+
return ReferenceOwnershipOptionality::Allowed;
107+
case ReferenceOwnership::Weak:
108+
return ReferenceOwnershipOptionality::Required;
109+
case ReferenceOwnership::Unowned:
110+
return ReferenceOwnershipOptionality::Disallowed;
111+
case ReferenceOwnership::Unmanaged:
112+
return ReferenceOwnershipOptionality::AllowedIfImporting;
113+
}
114+
llvm_unreachable("impossible");
115+
}
49116

50117
/// Diagnostic printing of \c StaticSpellingKind.
51118
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ReferenceOwnership RO);
@@ -60,8 +127,12 @@ enum class ValueOwnership : uint8_t {
60127
/// \brief a '__shared' non-mutating pointer-like value
61128
Shared,
62129
/// \brief an '__owned' value
63-
Owned
130+
Owned,
131+
132+
Last_Kind = Owned
64133
};
134+
enum : unsigned { NumValueOwnershipBits =
135+
countBitsUsed(static_cast<unsigned>(ValueOwnership::Last_Kind)) };
65136

66137
} // end namespace swift
67138

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
//===--- ReferenceStorage.def - Non-default reference storage ---*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2018 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+
// This file defines non-default reference storage kind macros used for
14+
// macro-metaprogramming.
15+
//
16+
//===----------------------------------------------------------------------===//
17+
18+
/// There are two fundamental reference storage types: checked and unchecked.
19+
/// Checked storage types have runtime enforced correctness.
20+
/// Unchecked storage types have no runtime enforced correctness.
21+
///
22+
/// Checked reference storage types are also subcategorized by loadability.
23+
/// * Always loadable: The compiler may move the reference or use registers.
24+
/// * Never loadable: The runtime (etc) tracks the address of the reference.
25+
/// * Sometimes loadable: If the reference is a native object, then it is
26+
/// always loadable. Otherwise fall back to never loadable semantics, a.k.a.
27+
/// "address only".
28+
///
29+
/// Unchecked reference storage types are always loadable.
30+
///
31+
/// The primary macros therefore are:
32+
/// * ALWAYS_LOADABLE_CHECKED_REF_STORAGE
33+
/// * SOMETIMES_LOADABLE_CHECKED_REF_STORAGE
34+
/// * NEVER_LOADABLE_CHECKED_REF_STORAGE
35+
/// * UNCHECKED_REF_STORAGE
36+
///
37+
/// Helper macros include:
38+
/// * CHECKED_REF_STORAGE -- Any checked reference storage type. Specifically
39+
/// "always", "sometimes", and "never" -- but not "unchecked".
40+
/// * LOADABLE_REF_STORAGE -- Any loadable reference storage type. Specifically
41+
/// "always", "sometimes", and "unchecked" -- but not "never".
42+
/// * ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE -- self describing.
43+
/// * NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE -- self describing.
44+
///
45+
/// SUBSYSTEMS NOTES
46+
///
47+
/// In general, reference storage types are barely visible in the user facing
48+
/// type system and therefore AST clients above SIL can get away with
49+
/// just REF_STORAGE, or CHECKED_REF_STORAGE with UNCHECKED_REF_STORAGE.
50+
///
51+
/// When it comes to SIL aware AST clients, loadability matters. The best way
52+
/// to understand how the helper macros are used is to look at SILNodes.def.
53+
/// What follows is a short -- possibly not up to date -- summary:
54+
///
55+
/// UNCHECKED_REF_STORAGE
56+
/// Name##RetainValueInst
57+
/// Name##ReleaseValueInst
58+
/// LOADABLE_REF_STORAGE
59+
/// Ref*ToNameInst
60+
/// Name*ToRefInst
61+
/// NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE
62+
/// Load##Name##Inst
63+
/// Store##Name##Inst
64+
/// ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE
65+
/// Copy##Name##ValueInst
66+
/// StrongRetain##Name##Inst
67+
/// Name##RetainInst
68+
/// Name##ReleaseInst
69+
///
70+
/// After helper macro expansion:
71+
///
72+
/// UNCHECKED_REF_STORAGE
73+
/// Ref*ToNameInst
74+
/// Name*ToRefInst
75+
/// Name##RetainValueInst
76+
/// Name##ReleaseValueInst
77+
/// ALWAYS_LOADABLE_CHECKED_REF_STORAGE
78+
/// Ref*ToNameInst
79+
/// Name*ToRefInst
80+
/// Copy##Name##ValueInst
81+
/// StrongRetain##Name##Inst
82+
/// Name##RetainInst
83+
/// Name##ReleaseInst
84+
/// SOMETIMES_LOADABLE_CHECKED_REF_STORAGE
85+
/// Ref*ToNameInst
86+
/// Name*ToRefInst
87+
/// Load##Name##Inst
88+
/// Store##Name##Inst
89+
/// Copy##Name##ValueInst
90+
/// StrongRetain##Name##Inst
91+
/// Name##RetainInst
92+
/// Name##ReleaseInst
93+
/// NEVER_LOADABLE_CHECKED_REF_STORAGE
94+
/// Load##Name##Inst
95+
/// Store##Name##Inst
96+
///
97+
/// Finally, a note about IRGen: TypeInfos need to be created per reference
98+
/// storage type, and SOMETIMES_LOADABLE_CHECKED_REF_STORAGE needs *two*
99+
/// TypeInfos to be created. One for the loadable scenario, and one for the
100+
/// address-only scenario.
101+
102+
103+
#ifndef REF_STORAGE
104+
#define REF_STORAGE(Name, name, NAME)
105+
#endif
106+
107+
#ifdef ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE
108+
#if defined(ALWAYS_LOADABLE_CHECKED_REF_STORAGE) || \
109+
defined(SOMETIMES_LOADABLE_CHECKED_REF_STORAGE)
110+
#error Overlapping meta-programming macros
111+
#endif
112+
#define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \
113+
ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME)
114+
#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \
115+
ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME)
116+
#endif
117+
118+
#ifdef NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE
119+
#if defined(NEVER_LOADABLE_CHECKED_REF_STORAGE) || \
120+
defined(SOMETIMES_LOADABLE_CHECKED_REF_STORAGE)
121+
#error Overlapping meta-programming macros
122+
#endif
123+
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \
124+
NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME)
125+
#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \
126+
NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME)
127+
#endif
128+
129+
#ifdef LOADABLE_REF_STORAGE
130+
#if defined(ALWAYS_LOADABLE_CHECKED_REF_STORAGE) || \
131+
defined(SOMETIMES_LOADABLE_CHECKED_REF_STORAGE) || \
132+
defined(UNCHECKED_REF_STORAGE)
133+
#error Overlapping meta-programming macros
134+
#endif
135+
#define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \
136+
LOADABLE_REF_STORAGE(Name, name, NAME)
137+
#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \
138+
LOADABLE_REF_STORAGE(Name, name, NAME)
139+
#define UNCHECKED_REF_STORAGE(Name, name, NAME) \
140+
LOADABLE_REF_STORAGE(Name, name, NAME)
141+
#endif
142+
143+
#ifdef CHECKED_REF_STORAGE
144+
#if defined(SOMETIMES_LOADABLE_CHECKED_REF_STORAGE) || \
145+
defined(ALWAYS_LOADABLE_CHECKED_REF_STORAGE) || \
146+
defined(NEVER_LOADABLE_CHECKED_REF_STORAGE)
147+
#error Overlapping meta-programming macros
148+
#endif
149+
#define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \
150+
CHECKED_REF_STORAGE(Name, name, NAME)
151+
#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \
152+
CHECKED_REF_STORAGE(Name, name, NAME)
153+
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \
154+
CHECKED_REF_STORAGE(Name, name, NAME)
155+
#endif
156+
157+
#ifndef NEVER_LOADABLE_CHECKED_REF_STORAGE
158+
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \
159+
REF_STORAGE(Name, name, NAME)
160+
#endif
161+
162+
#ifndef SOMETIMES_LOADABLE_CHECKED_REF_STORAGE
163+
#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \
164+
REF_STORAGE(Name, name, NAME)
165+
#endif
166+
167+
#ifndef ALWAYS_LOADABLE_CHECKED_REF_STORAGE
168+
#define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, name, NAME) \
169+
REF_STORAGE(Name, name, NAME)
170+
#endif
171+
172+
#ifndef UNCHECKED_REF_STORAGE
173+
#define UNCHECKED_REF_STORAGE(Name, name, NAME) \
174+
REF_STORAGE(Name, name, NAME)
175+
#endif
176+
177+
#ifndef REF_STORAGE_RANGE
178+
#define REF_STORAGE_RANGE(First, Last)
179+
#endif
180+
181+
// NOTE: You will need to update ReferenceOwnership in ModuleFormat.h.
182+
NEVER_LOADABLE_CHECKED_REF_STORAGE(Weak, weak, WEAK)
183+
SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Unowned, unowned, UNOWNED)
184+
UNCHECKED_REF_STORAGE(Unmanaged, unmanaged, UNMANAGED)
185+
REF_STORAGE_RANGE(Weak, Unmanaged)
186+
187+
#undef REF_STORAGE
188+
#undef NEVER_LOADABLE_CHECKED_REF_STORAGE
189+
#undef ALWAYS_LOADABLE_CHECKED_REF_STORAGE
190+
#undef SOMETIMES_LOADABLE_CHECKED_REF_STORAGE
191+
#undef UNCHECKED_REF_STORAGE
192+
#undef REF_STORAGE_RANGE
193+
194+
#undef ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE
195+
#undef NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE
196+
#undef LOADABLE_REF_STORAGE
197+
#undef CHECKED_REF_STORAGE

0 commit comments

Comments
 (0)