1818
1919#include " swift/AST/Type.h"
2020#include " llvm/ADT/Hashing.h"
21+ #include " llvm/ADT/StringSwitch.h"
22+ #include " llvm/Support/Debug.h"
23+ #include " llvm/Support/raw_ostream.h"
2124
2225namespace llvm {
2326class raw_ostream ;
@@ -80,21 +83,25 @@ class ActorIsolation {
8083 };
8184 unsigned kind : 3 ;
8285 unsigned isolatedByPreconcurrency : 1 ;
83- unsigned parameterIndex : 28 ;
86+
87+ // / Set to true if this was parsed from SIL.
88+ unsigned silParsed : 1 ;
89+
90+ unsigned parameterIndex : 27 ;
8491
8592 ActorIsolation (Kind kind, NominalTypeDecl *actor, unsigned parameterIndex);
8693
8794 ActorIsolation (Kind kind, VarDecl *capturedActor);
8895
8996 ActorIsolation (Kind kind, Type globalActor)
9097 : globalActor(globalActor), kind(kind), isolatedByPreconcurrency(false ),
91- parameterIndex (0 ) { }
98+ silParsed ( false ), parameterIndex(0 ) {}
9299
93100public:
94101 // No-argument constructor needed for DenseMap use in PostfixCompletion.cpp
95- explicit ActorIsolation (Kind kind = Unspecified)
102+ explicit ActorIsolation (Kind kind = Unspecified, bool isSILParsed = false )
96103 : pointer(nullptr ), kind(kind), isolatedByPreconcurrency(false ),
97- parameterIndex(0 ) { }
104+ silParsed(isSILParsed), parameterIndex(0 ) {}
98105
99106 static ActorIsolation forUnspecified () {
100107 return ActorIsolation (Unspecified, nullptr );
@@ -122,6 +129,27 @@ class ActorIsolation {
122129 unsafe ? GlobalActorUnsafe : GlobalActor, globalActor);
123130 }
124131
132+ static std::optional<ActorIsolation> forSILString (StringRef string) {
133+ auto kind =
134+ llvm::StringSwitch<std::optional<ActorIsolation::Kind>>(string)
135+ .Case (" unspecified" ,
136+ std::optional<ActorIsolation>(ActorIsolation::Unspecified))
137+ .Case (" actor_instance" ,
138+ std::optional<ActorIsolation>(ActorIsolation::ActorInstance))
139+ .Case (" nonisolated" ,
140+ std::optional<ActorIsolation>(ActorIsolation::Nonisolated))
141+ .Case (" nonisolated_unsafe" , std::optional<ActorIsolation>(
142+ ActorIsolation::NonisolatedUnsafe))
143+ .Case (" global_actor" ,
144+ std::optional<ActorIsolation>(ActorIsolation::GlobalActor))
145+ .Case (" global_actor_unsafe" , std::optional<ActorIsolation>(
146+ ActorIsolation::GlobalActorUnsafe))
147+ .Default (std::nullopt );
148+ if (kind == std::nullopt )
149+ return std::nullopt ;
150+ return ActorIsolation (*kind, true /* is sil parsed*/ );
151+ }
152+
125153 Kind getKind () const { return (Kind)kind; }
126154
127155 operator Kind () const { return getKind (); }
@@ -140,6 +168,8 @@ class ActorIsolation {
140168 return parameterIndex;
141169 }
142170
171+ bool isSILParsed () const { return silParsed; }
172+
143173 bool isActorIsolated () const {
144174 switch (getKind ()) {
145175 case ActorInstance:
@@ -168,6 +198,10 @@ class ActorIsolation {
168198
169199 Type getGlobalActor () const {
170200 assert (isGlobalActor ());
201+
202+ if (silParsed)
203+ return Type ();
204+
171205 return globalActor;
172206 }
173207
@@ -222,6 +256,32 @@ class ActorIsolation {
222256 state.kind , state.pointer , state.isolatedByPreconcurrency ,
223257 state.parameterIndex );
224258 }
259+
260+ void print (llvm::raw_ostream &os) const {
261+ switch (getKind ()) {
262+ case Unspecified:
263+ os << " unspecified" ;
264+ return ;
265+ case ActorInstance:
266+ os << " actor_instance" ;
267+ return ;
268+ case Nonisolated:
269+ os << " nonisolated" ;
270+ return ;
271+ case NonisolatedUnsafe:
272+ os << " nonisolated_unsafe" ;
273+ return ;
274+ case GlobalActor:
275+ os << " global_actor" ;
276+ return ;
277+ case GlobalActorUnsafe:
278+ os << " global_actor_unsafe" ;
279+ return ;
280+ }
281+ llvm_unreachable (" Covered switch isn't covered?!" );
282+ }
283+
284+ SWIFT_DEBUG_DUMP { print (llvm::dbgs ()); }
225285};
226286
227287// / Determine how the given value declaration is isolated.
@@ -249,6 +309,51 @@ bool usesFlowSensitiveIsolation(AbstractFunctionDecl const *fn);
249309
250310void simple_display (llvm::raw_ostream &out, const ActorIsolation &state);
251311
312+ // ApplyIsolationCrossing records the source and target of an isolation crossing
313+ // within an ApplyExpr. In particular, it stores the isolation of the caller
314+ // and the callee of the ApplyExpr, to be used for inserting implicit actor
315+ // hops for implicitly async functions and to be used for diagnosing potential
316+ // data races that could arise when non-Sendable values are passed to calls
317+ // that cross isolation domains.
318+ struct ApplyIsolationCrossing {
319+ ActorIsolation CallerIsolation;
320+ ActorIsolation CalleeIsolation;
321+
322+ ApplyIsolationCrossing ()
323+ : CallerIsolation(ActorIsolation::forUnspecified()),
324+ CalleeIsolation (ActorIsolation::forUnspecified()) {}
325+
326+ ApplyIsolationCrossing (ActorIsolation CallerIsolation,
327+ ActorIsolation CalleeIsolation)
328+ : CallerIsolation(CallerIsolation), CalleeIsolation(CalleeIsolation) {}
329+
330+ // If the callee is not actor isolated, then this crossing exits isolation.
331+ // This method returns true iff this crossing exits isolation.
332+ bool exitsIsolation () const { return !CalleeIsolation.isActorIsolated (); }
333+
334+ // Whether to use the isolation of the caller or callee for generating
335+ // informative diagnostics depends on whether this crossing is an exit.
336+ // In particular, we tend to use the callee isolation for diagnostics,
337+ // but if this crossing is an exit from isolation then the callee isolation
338+ // is not very informative, so we use the caller isolation instead.
339+ ActorIsolation getDiagnoseIsolation () const {
340+ return exitsIsolation () ? CallerIsolation : CalleeIsolation;
341+ }
342+
343+ ActorIsolation getCallerIsolation () const { return CallerIsolation; }
344+ ActorIsolation getCalleeIsolation () const { return CalleeIsolation; }
345+ };
346+
252347} // end namespace swift
253348
349+ namespace llvm {
350+
351+ inline llvm::raw_ostream &operator <<(llvm::raw_ostream &os,
352+ const swift::ActorIsolation &other) {
353+ other.print (os);
354+ return os;
355+ }
356+
357+ } // namespace llvm
358+
254359#endif /* SWIFT_AST_ACTORISOLATIONSTATE_H */
0 commit comments