@@ -90,6 +90,187 @@ struct DenseMapInfo<swift::PartitionPrimitives::Region> {
9090
9191namespace swift {
9292
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+
93274struct TransferringOperand {
94275 using ValueType = llvm::PointerIntPair<Operand *, 1 >;
95276 ValueType value;
@@ -965,183 +1146,6 @@ class Partition {
9651146 }
9661147};
9671148
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-
11451149// / A data structure that applies a series of PartitionOps to a single Partition
11461150// / that it modifies.
11471151// /
0 commit comments