18
18
19
19
#include " swift/AST/Type.h"
20
20
#include " llvm/ADT/Hashing.h"
21
+ #include " llvm/ADT/StringSwitch.h"
22
+ #include " llvm/Support/Debug.h"
23
+ #include " llvm/Support/raw_ostream.h"
21
24
22
25
namespace llvm {
23
26
class raw_ostream ;
@@ -80,21 +83,25 @@ class ActorIsolation {
80
83
};
81
84
unsigned kind : 3 ;
82
85
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 ;
84
91
85
92
ActorIsolation (Kind kind, NominalTypeDecl *actor, unsigned parameterIndex);
86
93
87
94
ActorIsolation (Kind kind, VarDecl *capturedActor);
88
95
89
96
ActorIsolation (Kind kind, Type globalActor)
90
97
: globalActor(globalActor), kind(kind), isolatedByPreconcurrency(false ),
91
- parameterIndex (0 ) { }
98
+ silParsed ( false ), parameterIndex(0 ) {}
92
99
93
100
public:
94
101
// 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 )
96
103
: pointer(nullptr ), kind(kind), isolatedByPreconcurrency(false ),
97
- parameterIndex(0 ) { }
104
+ silParsed(isSILParsed), parameterIndex(0 ) {}
98
105
99
106
static ActorIsolation forUnspecified () {
100
107
return ActorIsolation (Unspecified, nullptr );
@@ -122,6 +129,27 @@ class ActorIsolation {
122
129
unsafe ? GlobalActorUnsafe : GlobalActor, globalActor);
123
130
}
124
131
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
+
125
153
Kind getKind () const { return (Kind)kind; }
126
154
127
155
operator Kind () const { return getKind (); }
@@ -140,6 +168,8 @@ class ActorIsolation {
140
168
return parameterIndex;
141
169
}
142
170
171
+ bool isSILParsed () const { return silParsed; }
172
+
143
173
bool isActorIsolated () const {
144
174
switch (getKind ()) {
145
175
case ActorInstance:
@@ -168,6 +198,10 @@ class ActorIsolation {
168
198
169
199
Type getGlobalActor () const {
170
200
assert (isGlobalActor ());
201
+
202
+ if (silParsed)
203
+ return Type ();
204
+
171
205
return globalActor;
172
206
}
173
207
@@ -222,6 +256,32 @@ class ActorIsolation {
222
256
state.kind , state.pointer , state.isolatedByPreconcurrency ,
223
257
state.parameterIndex );
224
258
}
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 ()); }
225
285
};
226
286
227
287
// / Determine how the given value declaration is isolated.
@@ -249,6 +309,51 @@ bool usesFlowSensitiveIsolation(AbstractFunctionDecl const *fn);
249
309
250
310
void simple_display (llvm::raw_ostream &out, const ActorIsolation &state);
251
311
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
+
252
347
} // end namespace swift
253
348
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
+
254
359
#endif /* SWIFT_AST_ACTORISOLATIONSTATE_H */
0 commit comments