13
13
#include " swift/SILOptimizer/Utils/PartitionUtils.h"
14
14
#include " swift/AST/Expr.h"
15
15
#include " swift/SIL/ApplySite.h"
16
+ #include " swift/SIL/InstructionUtils.h"
17
+ #include " swift/SIL/PatternMatch.h"
16
18
#include " swift/SIL/SILGlobalVariable.h"
17
19
#include " llvm/Support/CommandLine.h"
18
20
19
21
using namespace swift ;
22
+ using namespace swift ::PatternMatch;
20
23
using namespace swift ::PartitionPrimitives;
21
24
22
25
// ===----------------------------------------------------------------------===//
@@ -42,6 +45,28 @@ static llvm::cl::opt<bool, true> // The parser
42
45
// MARK: SILIsolationInfo
43
46
// ===----------------------------------------------------------------------===//
44
47
48
+ static std::optional<ActorIsolation>
49
+ getGlobalActorInitIsolation (SILFunction *fn) {
50
+ auto block = fn->begin ();
51
+
52
+ // Make sure our function has a single block. We should always have a single
53
+ // block today. Return nullptr otherwise.
54
+ if (block == fn->end () || std::next (block) != fn->end ())
55
+ return {};
56
+
57
+ GlobalAddrInst *gai = nullptr ;
58
+ if (!match (cast<SILInstruction>(block->getTerminator ()),
59
+ m_ReturnInst (m_AddressToPointerInst (m_GlobalAddrInst (gai)))))
60
+ return {};
61
+
62
+ auto *globalDecl = gai->getReferencedGlobal ()->getDecl ();
63
+ if (!globalDecl)
64
+ return {};
65
+
66
+ // See if our globalDecl is specifically guarded.
67
+ return getActorIsolation (globalDecl);
68
+ }
69
+
45
70
SILIsolationInfo SILIsolationInfo::get (SILInstruction *inst) {
46
71
if (ApplyExpr *apply = inst->getLoc ().getAsASTNode <ApplyExpr>()) {
47
72
if (auto crossing = apply->getIsolationCrossing ()) {
@@ -148,28 +173,113 @@ SILIsolationInfo SILIsolationInfo::get(SILInstruction *inst) {
148
173
}
149
174
}
150
175
176
+ // See if we have a struct_extract from a global actor isolated type.
177
+ if (auto *sei = dyn_cast<StructExtractInst>(inst)) {
178
+ return SILIsolationInfo::getActorIsolated (sei, sei->getStructDecl ());
179
+ }
180
+
181
+ // See if we have an unchecked_enum_data from a global actor isolated type.
182
+ if (auto *uedi = dyn_cast<UncheckedEnumDataInst>(inst)) {
183
+ return SILIsolationInfo::getActorIsolated (uedi, uedi->getEnumDecl ());
184
+ }
185
+
186
+ // Check if we have an unsafeMutableAddressor from a global actor, mark the
187
+ // returned value as being actor derived.
188
+ if (auto applySite = FullApplySite::isa (inst)) {
189
+ if (auto *calleeFunction = applySite.getCalleeFunction ()) {
190
+ if (calleeFunction->isGlobalInit ()) {
191
+ auto isolation = getGlobalActorInitIsolation (calleeFunction);
192
+ if (isolation && isolation->isGlobalActor ()) {
193
+ return SILIsolationInfo::getActorIsolated (SILValue (), *isolation);
194
+ }
195
+ }
196
+ }
197
+ }
198
+
199
+ // See if we have a convert function from a Sendable actor isolated function,
200
+ // we want to treat the result of the convert function as being actor isolated
201
+ // so that we cannot escape the value.
202
+ //
203
+ // NOTE: At this point, we already know that cfi's result is not sendable,
204
+ // since we would have exited above already.
205
+ if (auto *cfi = dyn_cast<ConvertFunctionInst>(inst)) {
206
+ SILValue operand = cfi->getOperand ();
207
+ if (operand->getType ().getAs <SILFunctionType>()->isSendable ()) {
208
+ SILValue newValue = operand;
209
+ do {
210
+ operand = newValue;
211
+
212
+ newValue = lookThroughOwnershipInsts (operand);
213
+ if (auto *ttfi = dyn_cast<ThinToThickFunctionInst>(newValue)) {
214
+ newValue = ttfi->getOperand ();
215
+ }
216
+
217
+ if (auto *cfi = dyn_cast<ConvertFunctionInst>(newValue)) {
218
+ newValue = cfi->getOperand ();
219
+ }
220
+
221
+ if (auto *pai = dyn_cast<PartialApplyInst>(newValue)) {
222
+ newValue = pai->getCallee ();
223
+ }
224
+ } while (newValue != operand);
225
+
226
+ if (auto *ai = dyn_cast<ApplyInst>(operand)) {
227
+ if (auto *callExpr = ai->getLoc ().getAsASTNode <ApplyExpr>()) {
228
+ if (auto *callType = callExpr->getType ()->getAs <AnyFunctionType>()) {
229
+ if (callType->hasGlobalActor ()) {
230
+ return SILIsolationInfo::getGlobalActorIsolated (
231
+ ai, callType->getGlobalActor ());
232
+ }
233
+ }
234
+ }
235
+ }
236
+
237
+ if (auto *fri = dyn_cast<FunctionRefInst>(operand)) {
238
+ if (auto isolation = SILIsolationInfo::get (fri)) {
239
+ return isolation;
240
+ }
241
+ }
242
+ }
243
+ }
244
+
151
245
return SILIsolationInfo ();
152
246
}
153
247
154
- SILIsolationInfo SILIsolationInfo::get (SILFunctionArgument *arg) {
248
+ SILIsolationInfo SILIsolationInfo::get (SILArgument *arg) {
249
+ // Handle a switch_enum from a global actor isolated type.
250
+ if (auto *phiArg = dyn_cast<SILPhiArgument>(arg)) {
251
+ if (auto *singleTerm = phiArg->getSingleTerminator ()) {
252
+ if (auto *swi = dyn_cast<SwitchEnumInst>(singleTerm)) {
253
+ auto enumDecl =
254
+ swi->getOperand ()->getType ().getEnumOrBoundGenericEnum ();
255
+ return SILIsolationInfo::getActorIsolated (arg, enumDecl);
256
+ }
257
+ }
258
+ return SILIsolationInfo ();
259
+ }
260
+
261
+ auto *fArg = cast<SILFunctionArgument>(arg);
262
+
155
263
// Transferring is always disconnected.
156
- if (!arg->isIndirectResult () && !arg->isIndirectErrorResult () &&
157
- arg->isTransferring ())
264
+ if (!fArg ->isIndirectResult () && !fArg ->isIndirectErrorResult () &&
265
+ ((fArg ->isClosureCapture () &&
266
+ fArg ->getFunction ()->getLoweredFunctionType ()->isSendable ()) ||
267
+ fArg ->isTransferring ()))
158
268
return SILIsolationInfo::getDisconnected ();
159
269
160
270
// If we have self and our function is actor isolated, all of our arguments
161
271
// should be marked as actor isolated.
162
- if (auto *self = arg ->getFunction ()->maybeGetSelfArgument ()) {
163
- if (auto functionIsolation = arg ->getFunction ()->getActorIsolation ()) {
272
+ if (auto *self = fArg ->getFunction ()->maybeGetSelfArgument ()) {
273
+ if (auto functionIsolation = fArg ->getFunction ()->getActorIsolation ()) {
164
274
if (functionIsolation.isActorIsolated ()) {
165
275
if (auto *nomDecl = self->getType ().getNominalOrBoundGenericNominal ()) {
166
- return SILIsolationInfo::getActorIsolated (arg , nomDecl);
276
+ return SILIsolationInfo::getActorIsolated (fArg , nomDecl);
167
277
}
168
278
}
169
279
}
170
280
}
171
281
172
- if (auto *decl = arg ->getDecl ()) {
282
+ if (auto *decl = fArg ->getDecl ()) {
173
283
auto isolation = swift::getActorIsolation (const_cast <ValueDecl *>(decl));
174
284
if (!bool (isolation)) {
175
285
if (auto *dc = decl->getDeclContext ()) {
@@ -178,11 +288,11 @@ SILIsolationInfo SILIsolationInfo::get(SILFunctionArgument *arg) {
178
288
}
179
289
180
290
if (isolation.isActorIsolated ()) {
181
- return SILIsolationInfo::getActorIsolated (arg , isolation);
291
+ return SILIsolationInfo::getActorIsolated (fArg , isolation);
182
292
}
183
293
}
184
294
185
- return SILIsolationInfo::getTaskIsolated (arg );
295
+ return SILIsolationInfo::getTaskIsolated (fArg );
186
296
}
187
297
188
298
void SILIsolationInfo::print (llvm::raw_ostream &os) const {
0 commit comments