@@ -90,6 +90,187 @@ struct DenseMapInfo<swift::PartitionPrimitives::Region> {
90
90
91
91
namespace swift {
92
92
93
+ class IsolationRegionInfo {
94
+ public:
95
+ // / The lattice is:
96
+ // /
97
+ // / Unknown -> Disconnected -> TransferringParameter -> Task -> Actor.
98
+ // /
99
+ // / Unknown means no information. We error when merging on it.
100
+ enum Kind {
101
+ Unknown,
102
+ Disconnected,
103
+ Task,
104
+ Actor,
105
+ };
106
+
107
+ private:
108
+ Kind kind;
109
+ // clang-format off
110
+ std::variant<
111
+ // Used for actor isolated when we have ActorIsolation info from the AST.
112
+ std::optional<ActorIsolation>,
113
+ // Used for actor isolation when we infer the actor at the SIL level.
114
+ NominalTypeDecl *,
115
+ // The task isolated parameter when we find a task isolated value.
116
+ SILValue
117
+ > data;
118
+ // clang-format on
119
+
120
+ IsolationRegionInfo (Kind kind, std::optional<ActorIsolation> actorIsolation)
121
+ : kind(kind), data(actorIsolation) {}
122
+ IsolationRegionInfo (Kind kind, NominalTypeDecl *decl)
123
+ : kind(kind), data(decl) {}
124
+
125
+ IsolationRegionInfo (Kind kind, SILValue value) : kind(kind), data(value) {}
126
+
127
+ public:
128
+ IsolationRegionInfo () : kind(Kind::Unknown), data() {}
129
+
130
+ operator bool () const { return kind != Kind::Unknown; }
131
+
132
+ operator Kind () const { return kind; }
133
+
134
+ Kind getKind () const { return kind; }
135
+
136
+ bool isDisconnected () const { return kind == Kind::Disconnected; }
137
+ bool isActorIsolated () const { return kind == Kind::Actor; }
138
+ bool isTaskIsolated () const { return kind == Kind::Task; }
139
+
140
+ void print (llvm::raw_ostream &os) const {
141
+ switch (Kind (*this )) {
142
+ case Unknown:
143
+ os << " unknown" ;
144
+ return ;
145
+ case Disconnected:
146
+ os << " disconnected" ;
147
+ return ;
148
+ case Actor:
149
+ os << " actor" ;
150
+ return ;
151
+ case Task:
152
+ os << " task" ;
153
+ return ;
154
+ }
155
+ }
156
+
157
+ void printForDiagnostics (llvm::raw_ostream &os) const ;
158
+
159
+ SWIFT_DEBUG_DUMP {
160
+ print (llvm::dbgs ());
161
+ llvm::dbgs () << ' \n ' ;
162
+ }
163
+
164
+ std::optional<ActorIsolation> getActorIsolation () const {
165
+ assert (kind == Actor);
166
+ assert (std::holds_alternative<std::optional<ActorIsolation>>(data) &&
167
+ " Doesn't have an actor isolation?!" );
168
+ return std::get<std::optional<ActorIsolation>>(data);
169
+ }
170
+
171
+ NominalTypeDecl *getActorInstance () const {
172
+ assert (kind == Actor);
173
+ assert (std::holds_alternative<NominalTypeDecl *>(data) &&
174
+ " Doesn't have an actor instance?!" );
175
+ return std::get<NominalTypeDecl *>(data);
176
+ }
177
+
178
+ SILValue getTaskIsolatedValue () const {
179
+ assert (kind == Task);
180
+ assert (std::holds_alternative<SILValue>(data) &&
181
+ " Doesn't have a task isolated value" );
182
+ return std::get<SILValue>(data);
183
+ }
184
+
185
+ bool hasActorIsolation () const {
186
+ return kind == Actor &&
187
+ std::holds_alternative<std::optional<ActorIsolation>>(data);
188
+ }
189
+
190
+ bool hasActorInstance () const {
191
+ return kind == Actor && std::holds_alternative<NominalTypeDecl *>(data);
192
+ }
193
+
194
+ bool hasTaskIsolatedValue () const {
195
+ return kind == Task && std::holds_alternative<SILValue>(data);
196
+ }
197
+
198
+ // / If we actually have an actor decl, return that. Otherwise, see if we have
199
+ // / an actor isolation if we can find one in there. Returns nullptr if we
200
+ // / fail.
201
+ NominalTypeDecl *tryInferActorDecl () const {
202
+ if (hasActorIsolation ()) {
203
+ auto actorIsolation = getActorIsolation ();
204
+ if (auto *actor = actorIsolation->getActorOrNullPtr ()) {
205
+ return actor;
206
+ }
207
+ return nullptr ;
208
+ }
209
+
210
+ if (hasActorInstance ()) {
211
+ auto actorDecl = getActorInstance ();
212
+ return actorDecl;
213
+ }
214
+
215
+ return nullptr ;
216
+ }
217
+
218
+ [[nodiscard]] IsolationRegionInfo merge (IsolationRegionInfo other) const {
219
+ // If we are greater than the other kind, then we are further along the
220
+ // lattice. We ignore the change.
221
+ if (unsigned (other.kind ) < unsigned (kind))
222
+ return *this ;
223
+
224
+ // TODO: Make this failing mean that we emit an unknown SIL error instead of
225
+ // asserting.
226
+ if (other.isActorIsolated () && isActorIsolated ()) {
227
+ if (other.hasActorInstance () && hasActorInstance ()) {
228
+ assert (other.getActorInstance () == getActorInstance () &&
229
+ " Actor should never be merged with another actor unless with "
230
+ " the same actor?!" );
231
+ } else if (other.hasActorIsolation () && hasActorIsolation ()) {
232
+ assert (other.getActorIsolation () == getActorIsolation () &&
233
+ " Actor should never be merged with another actor unless with "
234
+ " the same actor?!" );
235
+ }
236
+ }
237
+
238
+ // Otherwise, take the other value.
239
+ return other;
240
+ }
241
+
242
+ IsolationRegionInfo withActorIsolated (ActorIsolation isolation) {
243
+ return IsolationRegionInfo::getActorIsolated (isolation);
244
+ }
245
+
246
+ static IsolationRegionInfo getDisconnected () {
247
+ return {Kind::Disconnected, {}};
248
+ }
249
+
250
+ static IsolationRegionInfo getActorIsolated (ActorIsolation actorIsolation) {
251
+ return {Kind::Actor, actorIsolation};
252
+ }
253
+
254
+ // / Sometimes we may have something that is actor isolated or that comes from
255
+ // / a type. First try getActorIsolation and otherwise, just use the type.
256
+ static IsolationRegionInfo getActorIsolated (NominalTypeDecl *nomDecl) {
257
+ auto actorIsolation = swift::getActorIsolation (nomDecl);
258
+ if (actorIsolation.isActorIsolated ())
259
+ return getActorIsolated (actorIsolation);
260
+ if (nomDecl->isActor ())
261
+ return {Kind::Actor, nomDecl};
262
+ return {};
263
+ }
264
+
265
+ static IsolationRegionInfo getTaskIsolated (SILValue value) {
266
+ return {Kind::Task, value};
267
+ }
268
+ };
269
+
270
+ } // namespace swift
271
+
272
+ namespace swift {
273
+
93
274
struct TransferringOperand {
94
275
using ValueType = llvm::PointerIntPair<Operand *, 1 >;
95
276
ValueType value;
@@ -965,183 +1146,6 @@ class Partition {
965
1146
}
966
1147
};
967
1148
968
- class IsolationRegionInfo {
969
- public:
970
- // / The lattice is:
971
- // /
972
- // / Unknown -> Disconnected -> TransferringParameter -> Task -> Actor.
973
- // /
974
- // / Unknown means no information. We error when merging on it.
975
- enum Kind {
976
- Unknown,
977
- Disconnected,
978
- Task,
979
- Actor,
980
- };
981
-
982
- private:
983
- Kind kind;
984
- // clang-format off
985
- std::variant<
986
- // Used for actor isolated when we have ActorIsolation info from the AST.
987
- std::optional<ActorIsolation>,
988
- // Used for actor isolation when we infer the actor at the SIL level.
989
- NominalTypeDecl *,
990
- // The task isolated parameter when we find a task isolated value.
991
- SILValue
992
- > data;
993
- // clang-format on
994
-
995
- IsolationRegionInfo (Kind kind, std::optional<ActorIsolation> actorIsolation)
996
- : kind(kind), data(actorIsolation) {}
997
- IsolationRegionInfo (Kind kind, NominalTypeDecl *decl)
998
- : kind(kind), data(decl) {}
999
-
1000
- IsolationRegionInfo (Kind kind, SILValue value) : kind(kind), data(value) {}
1001
-
1002
- public:
1003
- IsolationRegionInfo () : kind(Kind::Unknown), data() {}
1004
-
1005
- operator bool () const { return kind != Kind::Unknown; }
1006
-
1007
- operator Kind () const { return kind; }
1008
-
1009
- Kind getKind () const { return kind; }
1010
-
1011
- bool isDisconnected () const { return kind == Kind::Disconnected; }
1012
- bool isActorIsolated () const { return kind == Kind::Actor; }
1013
- bool isTaskIsolated () const { return kind == Kind::Task; }
1014
-
1015
- void print (llvm::raw_ostream &os) const {
1016
- switch (Kind (*this )) {
1017
- case Unknown:
1018
- os << " unknown" ;
1019
- return ;
1020
- case Disconnected:
1021
- os << " disconnected" ;
1022
- return ;
1023
- case Actor:
1024
- os << " actor" ;
1025
- return ;
1026
- case Task:
1027
- os << " task" ;
1028
- return ;
1029
- }
1030
- }
1031
-
1032
- void printForDiagnostics (llvm::raw_ostream &os) const ;
1033
-
1034
- SWIFT_DEBUG_DUMP {
1035
- print (llvm::dbgs ());
1036
- llvm::dbgs () << ' \n ' ;
1037
- }
1038
-
1039
- std::optional<ActorIsolation> getActorIsolation () const {
1040
- assert (kind == Actor);
1041
- assert (std::holds_alternative<std::optional<ActorIsolation>>(data) &&
1042
- " Doesn't have an actor isolation?!" );
1043
- return std::get<std::optional<ActorIsolation>>(data);
1044
- }
1045
-
1046
- NominalTypeDecl *getActorInstance () const {
1047
- assert (kind == Actor);
1048
- assert (std::holds_alternative<NominalTypeDecl *>(data) &&
1049
- " Doesn't have an actor instance?!" );
1050
- return std::get<NominalTypeDecl *>(data);
1051
- }
1052
-
1053
- SILValue getTaskIsolatedValue () const {
1054
- assert (kind == Task);
1055
- assert (std::holds_alternative<SILValue>(data) &&
1056
- " Doesn't have a task isolated value" );
1057
- return std::get<SILValue>(data);
1058
- }
1059
-
1060
- bool hasActorIsolation () const {
1061
- return kind == Actor &&
1062
- std::holds_alternative<std::optional<ActorIsolation>>(data);
1063
- }
1064
-
1065
- bool hasActorInstance () const {
1066
- return kind == Actor && std::holds_alternative<NominalTypeDecl *>(data);
1067
- }
1068
-
1069
- bool hasTaskIsolatedValue () const {
1070
- return kind == Task && std::holds_alternative<SILValue>(data);
1071
- }
1072
-
1073
- // / If we actually have an actor decl, return that. Otherwise, see if we have
1074
- // / an actor isolation if we can find one in there. Returns nullptr if we
1075
- // / fail.
1076
- NominalTypeDecl *tryInferActorDecl () const {
1077
- if (hasActorIsolation ()) {
1078
- auto actorIsolation = getActorIsolation ();
1079
- if (auto *actor = actorIsolation->getActorOrNullPtr ()) {
1080
- return actor;
1081
- }
1082
- return nullptr ;
1083
- }
1084
-
1085
- if (hasActorInstance ()) {
1086
- auto actorDecl = getActorInstance ();
1087
- return actorDecl;
1088
- }
1089
-
1090
- return nullptr ;
1091
- }
1092
-
1093
- [[nodiscard]] IsolationRegionInfo merge (IsolationRegionInfo other) const {
1094
- // If we are greater than the other kind, then we are further along the
1095
- // lattice. We ignore the change.
1096
- if (unsigned (other.kind ) < unsigned (kind))
1097
- return *this ;
1098
-
1099
- // TODO: Make this failing mean that we emit an unknown SIL error instead of
1100
- // asserting.
1101
- if (other.isActorIsolated () && isActorIsolated ()) {
1102
- if (other.hasActorInstance () && hasActorInstance ()) {
1103
- assert (other.getActorInstance () == getActorInstance () &&
1104
- " Actor should never be merged with another actor unless with "
1105
- " the same actor?!" );
1106
- } else if (other.hasActorIsolation () && hasActorIsolation ()) {
1107
- assert (other.getActorIsolation () == getActorIsolation () &&
1108
- " Actor should never be merged with another actor unless with "
1109
- " the same actor?!" );
1110
- }
1111
- }
1112
-
1113
- // Otherwise, take the other value.
1114
- return other;
1115
- }
1116
-
1117
- IsolationRegionInfo withActorIsolated (ActorIsolation isolation) {
1118
- return IsolationRegionInfo::getActorIsolated (isolation);
1119
- }
1120
-
1121
- static IsolationRegionInfo getDisconnected () {
1122
- return {Kind::Disconnected, {}};
1123
- }
1124
-
1125
- static IsolationRegionInfo getActorIsolated (ActorIsolation actorIsolation) {
1126
- return {Kind::Actor, actorIsolation};
1127
- }
1128
-
1129
- // / Sometimes we may have something that is actor isolated or that comes from
1130
- // / a type. First try getActorIsolation and otherwise, just use the type.
1131
- static IsolationRegionInfo getActorIsolated (NominalTypeDecl *nomDecl) {
1132
- auto actorIsolation = swift::getActorIsolation (nomDecl);
1133
- if (actorIsolation.isActorIsolated ())
1134
- return getActorIsolated (actorIsolation);
1135
- if (nomDecl->isActor ())
1136
- return {Kind::Actor, nomDecl};
1137
- return {};
1138
- }
1139
-
1140
- static IsolationRegionInfo getTaskIsolated (SILValue value) {
1141
- return {Kind::Task, value};
1142
- }
1143
- };
1144
-
1145
1149
// / A data structure that applies a series of PartitionOps to a single Partition
1146
1150
// / that it modifies.
1147
1151
// /
0 commit comments