Skip to content

Commit 9875bcf

Browse files
authored
Merge pull request swiftlang#39992 from DougGregor/actor-transport-sil-cleanup
2 parents 3290833 + 3da14e6 commit 9875bcf

File tree

10 files changed

+209
-264
lines changed

10 files changed

+209
-264
lines changed

include/swift/AST/KnownSDKTypes.def

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ KNOWN_SDK_TYPE_DECL(Concurrency, TaskLocal, ClassDecl, 1)
4545

4646
// Distributed actors
4747
KNOWN_SDK_TYPE_DECL(Distributed, DistributedActor, ProtocolDecl, 0)
48-
KNOWN_SDK_TYPE_DECL(Distributed, ActorTransport, ProtocolDecl, 0)
4948
KNOWN_SDK_TYPE_DECL(Distributed, ActorIdentity, ProtocolDecl, 0)
5049
KNOWN_SDK_TYPE_DECL(Distributed, AnyActorIdentity, StructDecl, 0)
5150

include/swift/SILOptimizer/Utils/DistributedActor.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,43 @@
1313
#ifndef SWIFT_SILOPTIMIZER_UTILS_DISTRIBUTED_ACTOR_H
1414
#define SWIFT_SILOPTIMIZER_UTILS_DISTRIBUTED_ACTOR_H
1515

16+
#include "llvm/ADT/ArrayRef.h"
17+
#include "llvm/ADT/Optional.h"
18+
#include <utility>
19+
1620
namespace swift {
1721

1822
class ASTContext;
1923
class ConstructorDecl;
2024
class ClassDecl;
25+
class DeclName;
26+
class SILBasicBlock;
2127
class SILBuilder;
2228
class SILArgument;
2329
class SILFunction;
2430
class SILLocation;
31+
class SILType;
2532
class SILValue;
2633

2734
/// Finds the first `ActorTransport`-compatible parameter of the given function.
2835
/// \returns nullptr if the function does not have such a parameter.
2936
SILArgument *findFirstActorTransportArg(SILFunction &F);
3037

38+
/// Emit a call to a witness of the actor transport protocol.
39+
///
40+
/// \param methodName The name of the method on the ActorTransport protocol.
41+
/// \param transport The transport on which to invoke the method
42+
/// \param actorType If non-empty, the type of the distributed actor that is
43+
/// provided as one of the arguments.
44+
/// \param args The arguments provided to the call, not including the transport.
45+
/// \param tryTargets For a call that can throw, the normal and error basic
46+
/// blocks that the call will branch to.
47+
void emitActorTransportWitnessCall(
48+
SILBuilder &B, SILLocation loc, DeclName methodName,
49+
SILValue transport, SILType actorType, llvm::ArrayRef<SILValue> args,
50+
llvm::Optional<std::pair<SILBasicBlock *, SILBasicBlock *>> tryTargets =
51+
llvm::None);
52+
3153
/// Emits code that notifies the distributed actor's transport that the
3254
/// actor is ready for execution.
3355
/// \param B the builder to use when emitting the code.

lib/SILGen/SILGenDistributed.cpp

Lines changed: 42 additions & 210 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,15 @@ static VarDecl* lookupProperty(NominalTypeDecl *ty, DeclName name) {
5252
static void initializeProperty(SILGenFunction &SGF, SILLocation loc,
5353
SILValue actorSelf,
5454
VarDecl* prop, SILValue value) {
55-
auto fieldAddr = SGF.B.createRefElementAddr(loc, actorSelf, prop,
56-
SGF.getLoweredType(prop->getInterfaceType()));
57-
SGF.B.createCopyAddr(loc,
58-
/*src*/value,
59-
/*dest*/fieldAddr,
60-
IsNotTake, IsInitialization);
55+
CanType propType = SGF.F.mapTypeIntoContext(prop->getInterfaceType())
56+
->getCanonicalType();
57+
SILType loweredPropType = SGF.getLoweredType(propType);
58+
auto fieldAddr = SGF.B.createRefElementAddr(loc, actorSelf, prop, loweredPropType);
59+
60+
if (fieldAddr->getType().isAddress())
61+
SGF.B.createCopyAddr(loc, value, fieldAddr, IsNotTake, IsInitialization);
62+
else
63+
SGF.B.emitStoreValueOperation(loc, value, fieldAddr, StoreOwnershipQualifier::Init);
6164
}
6265

6366
/******************************************************************************/
@@ -116,34 +119,7 @@ static void emitTransportInit(SILGenFunction &SGF,
116119
VarDecl *var = lookupProperty(classDecl, C.Id_actorTransport);
117120
assert(var);
118121

119-
// If the argument is not existential, it will be a concrete type
120-
// that can be erased to that existential.
121-
SILValue transportValue = transportArg;
122-
if (!transportArg->getType().isExistentialType()) {
123-
auto &existentialTL = SGF.getTypeLowering(var->getInterfaceType());
124-
auto concreteFormalType = transportArg->getType().getASTType();
125-
126-
auto archetype = OpenedArchetypeType::getAny(var->getInterfaceType());
127-
AbstractionPattern abstractionPattern(archetype);
128-
auto &concreteTL = SGF.getTypeLowering(abstractionPattern,
129-
concreteFormalType);
130-
131-
auto module = dc->getParentModule();
132-
auto actorTransportProto = C.getProtocol(KnownProtocolKind::ActorTransport);
133-
ProtocolConformanceRef conformances[] = {
134-
module->lookupConformance(concreteFormalType, actorTransportProto) };
135-
ManagedValue mv =
136-
SGF.emitExistentialErasure(loc, concreteFormalType,
137-
concreteTL, existentialTL,
138-
C.AllocateCopy(conformances),
139-
SGFContext(),
140-
[&](SGFContext C) -> ManagedValue {
141-
return ManagedValue::forBorrowedRValue(transportArg);
142-
});
143-
transportValue = mv.getValue();
144-
}
145-
146-
initializeProperty(SGF, loc, actorSelf.getValue(), var, transportValue);
122+
initializeProperty(SGF, loc, actorSelf.getValue(), var, transportArg);
147123
}
148124

149125
/// Emits the distributed actor's identity (`id`) initialization.
@@ -161,85 +137,27 @@ static void emitIdentityInit(SILGenFunction &SGF, ConstructorDecl *ctor,
161137
auto *dc = ctor->getDeclContext();
162138
auto classDecl = dc->getSelfClassDecl();
163139

164-
ProtocolDecl *transportProto = C.getProtocol(KnownProtocolKind::ActorTransport);
165-
ProtocolDecl *distributedActorProto = C.getProtocol(KnownProtocolKind::DistributedActor);
166-
167-
assert(distributedActorProto);
168-
assert(transportProto);
169-
170-
SILValue transportValue = findFirstActorTransportArg(F);
171-
172-
// --- Open the transport existential, if needed.
173-
auto transportASTType = transportValue->getType().getASTType();
174-
if (transportASTType->isAnyExistentialType()) {
175-
OpenedArchetypeType *Opened;
176-
transportASTType =
177-
transportASTType->openAnyExistentialType(Opened)->getCanonicalType();
178-
transportValue = B.createOpenExistentialAddr(
179-
loc, transportValue, F.getLoweredType(transportASTType),
180-
OpenedExistentialAccess::Immutable);
181-
}
182-
183140
// --- prepare `Self.self` metatype
184141
auto *selfTyDecl = ctor->getParent()->getSelfNominalTypeDecl();
185-
// This would be bad: since not ok for generic
186-
// auto selfMetatype = SGF.getLoweredType(selfTyDecl->getInterfaceType());
187-
auto selfMetatype =
188-
SGF.getLoweredType(F.mapTypeIntoContext(selfTyDecl->getInterfaceType()));
189-
// selfVarDecl.getType() // TODO: do this; then dont need the self type decl
142+
auto selfTy = F.mapTypeIntoContext(selfTyDecl->getDeclaredInterfaceType());
143+
auto selfMetatype = SGF.getLoweredType(MetatypeType::get(selfTy));
190144
SILValue selfMetatypeValue = B.createMetatype(loc, selfMetatype);
191145

192-
// === Make the transport.assignIdentity call
193-
// --- prepare the witness_method
194-
// Note: it does not matter on what module we perform the lookup,
195-
// it is currently ignored. So the Stdlib module is good enough.
196-
auto *module = SGF.getModule().getSwiftModule();
197-
198-
// the conformance here is just an abstract thing so we can simplify
199-
auto transportConfRef = ProtocolConformanceRef(transportProto);
200-
assert(!transportConfRef.isInvalid() && "Missing conformance to `ActorTransport`");
201-
202-
auto selfTy = F.mapTypeIntoContext(selfTyDecl->getDeclaredInterfaceType()); // TODO: thats just self var devl getType
203-
204-
auto distributedActorConfRef = module->lookupConformance(
205-
selfTy,
206-
distributedActorProto);
207-
assert(!distributedActorConfRef.isInvalid() && "Missing conformance to `DistributedActor`");
208-
209-
auto assignIdentityMethod =
210-
cast<FuncDecl>(transportProto->getSingleRequirement(C.Id_assignIdentity));
211-
auto assignIdentityRef = SILDeclRef(assignIdentityMethod, SILDeclRef::Kind::Func);
212-
auto assignIdentitySILTy =
213-
SGF.getConstantInfo(SGF.getTypeExpansionContext(), assignIdentityRef)
214-
.getSILType();
215-
216-
auto assignWitnessMethod = B.createWitnessMethod(
217-
loc,
218-
/*lookupTy*/transportASTType,
219-
/*Conformance*/transportConfRef,
220-
/*member*/assignIdentityRef,
221-
/*methodTy*/assignIdentitySILTy);
222-
223-
// --- prepare conformance subs
224-
auto genericSig = assignIdentityMethod->getGenericSignature();
225-
226-
SubstitutionMap subs =
227-
SubstitutionMap::get(genericSig,
228-
{transportASTType, selfTy},
229-
{transportConfRef, distributedActorConfRef});
230-
231-
VarDecl *var = lookupProperty(classDecl, C.Id_id);
146+
SILValue transport = findFirstActorTransportArg(F);
232147

233148
// --- create a temporary storage for the result of the call
234149
// it will be deallocated automatically as we exit this scope
235-
auto resultTy = SGF.getLoweredType(var->getInterfaceType());
150+
VarDecl *var = lookupProperty(classDecl, C.Id_id);
151+
auto resultTy = SGF.getLoweredType(
152+
F.mapTypeIntoContext(var->getInterfaceType()));
236153
auto temp = SGF.emitTemporaryAllocation(loc, resultTy);
237154

238-
// ---- actually call transport.assignIdentity(Self.self)
239-
B.createApply(
240-
loc, assignWitnessMethod, subs,
241-
{ temp, selfMetatypeValue, transportValue});
155+
// --- emit the call itself.
156+
emitActorTransportWitnessCall(
157+
B, loc, C.Id_assignIdentity, transport, SGF.getLoweredType(selfTy),
158+
{ temp, selfMetatypeValue });
242159

160+
// --- initialize the property.
243161
initializeProperty(SGF, loc, borrowedSelfArg.getValue(), var, temp);
244162
}
245163

@@ -282,74 +200,15 @@ static void createDistributedActorFactory_resolve(
282200
SILValue transportValue, Type selfTy, SILValue selfMetatypeValue,
283201
SILType resultTy, SILBasicBlock *normalBB, SILBasicBlock *errorBB) {
284202
auto &B = SGF.B;
285-
auto &SGM = SGF.SGM;
286-
auto &F = SGF.F;
287-
SILGenFunctionBuilder builder(SGM);
288203

289204
auto loc = SILLocation(fd);
290205
loc.markAutoGenerated();
291206

292-
ProtocolDecl *distributedActorProto =
293-
C.getProtocol(KnownProtocolKind::DistributedActor);
294-
ProtocolDecl *transportProto =
295-
C.getProtocol(KnownProtocolKind::ActorTransport);
296-
assert(distributedActorProto);
297-
assert(transportProto);
298-
299-
// // --- Open the transport existential
300-
OpenedArchetypeType *Opened;
301-
auto transportASTType = transportValue->getType().getASTType();
302-
auto openedTransportType =
303-
transportASTType->openAnyExistentialType(Opened)->getCanonicalType();
304-
auto openedTransportSILType = F.getLoweredType(openedTransportType);
305-
auto transportArchetypeValue =
306-
B.createOpenExistentialAddr(loc, transportValue, openedTransportSILType,
307-
OpenedExistentialAccess::Immutable);
308-
309-
// --- prepare the witness_method
310-
// Note: it does not matter on what module we perform the lookup,
311-
// it is currently ignored. So the Stdlib module is good enough.
312-
auto *module = SGF.getModule().getSwiftModule();
313-
314-
// the conformance here is just an abstract thing so we can simplify
315-
auto transportConfRef = ProtocolConformanceRef(transportProto);
316-
assert(!transportConfRef.isInvalid() &&
317-
"Missing conformance to `ActorTransport`");
318-
319-
auto distributedActorConfRef =
320-
module->lookupConformance(selfTy, distributedActorProto);
321-
assert(!distributedActorConfRef.isInvalid() &&
322-
"Missing conformance to `DistributedActor`");
323-
324-
auto resolveMethod =
325-
cast<FuncDecl>(transportProto->getSingleRequirement(C.Id_resolve));
326-
auto resolveRef = SILDeclRef(resolveMethod, SILDeclRef::Kind::Func);
327-
auto constantInfo =
328-
SGF.getConstantInfo(SGF.getTypeExpansionContext(), resolveRef);
329-
auto resolveSILTy = constantInfo.getSILType();
330-
331-
auto resolveWitnessMethod =
332-
B.createWitnessMethod(loc,
333-
/*lookupTy*/ openedTransportType,
334-
/*Conformance*/ transportConfRef,
335-
/*member*/ resolveRef,
336-
/*methodTy*/ resolveSILTy);
337-
338-
// // --- prepare conformance subs
339-
auto genericSig = resolveMethod->getGenericSignature();
340-
341-
SubstitutionMap subs =
342-
SubstitutionMap::get(genericSig, {openedTransportType, selfTy},
343-
{transportConfRef, distributedActorConfRef});
344-
345207
// // ---- actually call transport.resolve(id, as: Self.self)
346-
347-
SmallVector<SILValue, 3> params;
348-
params.push_back(identityValue);
349-
params.push_back(selfMetatypeValue);
350-
params.push_back(transportArchetypeValue); // self for the call, as last param
351-
352-
B.createTryApply(loc, resolveWitnessMethod, subs, params, normalBB, errorBB);
208+
emitActorTransportWitnessCall(
209+
B, loc, C.Id_resolve, transportValue, SGF.getLoweredType(selfTy),
210+
{ identityValue, selfMetatypeValue },
211+
std::make_pair(normalBB, errorBB));
353212
}
354213

355214
/// Function body of:
@@ -374,8 +233,6 @@ void SILGenFunction::emitDistributedActorFactory(FuncDecl *fd) {
374233

375234
// --- Parameter: transport
376235
SILArgument *transportArg = F.getArgument(1);
377-
assert(
378-
transportArg->getType().getASTType()->isEqual(C.getActorTransportType()));
379236

380237
SILValue selfArgValue = F.getSelfArgument();
381238
ManagedValue selfArg = ManagedValue::forUnmanaged(selfArgValue);
@@ -496,53 +353,28 @@ void SILGenFunction::emitResignIdentityCall(SILLocation loc,
496353
ASTContext &ctx = getASTContext();
497354

498355
FormalEvaluationScope scope(*this);
499-
356+
500357
// ==== locate: self.id
501358
auto *idVarDeclRef = lookupProperty(actorDecl, ctx.Id_id);
502-
auto idRef =
503-
B.createRefElementAddr(loc, actorSelf, idVarDeclRef,
504-
getLoweredType(idVarDeclRef->getType()));
505-
359+
CanType idType = F.mapTypeIntoContext(
360+
idVarDeclRef->getInterfaceType())->getCanonicalType();
361+
auto idRef = B.createRefElementAddr(loc, actorSelf, idVarDeclRef,
362+
getLoweredType(idType));
363+
506364
// ==== locate: self.actorTransport
507365
auto transportVarDeclRef = lookupProperty(actorDecl, ctx.Id_actorTransport);
366+
CanType transportType = F.mapTypeIntoContext(
367+
transportVarDeclRef->getInterfaceType())->getCanonicalType();
508368
auto transportRef =
509-
B.createRefElementAddr(loc, actorSelf, transportVarDeclRef,
510-
getLoweredType(transportVarDeclRef->getType()));
511-
512-
// ==== locate: self.transport.resignIdentity(...)
513-
auto *transportDecl = ctx.getActorTransportDecl();
514-
auto resignFnDecls = transportDecl->lookupDirect(ctx.Id_resignIdentity);
515-
assert(resignFnDecls.size() == 1);
516-
auto *resignFnDecl = resignFnDecls.front();
517-
auto resignFnRef = SILDeclRef(resignFnDecl);
518-
519-
// ==== perform the call
520-
auto openedTransport =
521-
OpenedArchetypeType::get(transportVarDeclRef->getType());
522-
auto transportAddr =
523-
B.createOpenExistentialAddr(loc, /*operand=*/transportRef.getValue(),
524-
getLoweredType(openedTransport),
525-
OpenedExistentialAccess::Immutable);
526-
527-
auto resignFnType =
528-
SGM.M.Types.getConstantFunctionType(TypeExpansionContext::minimal(),
529-
resignFnRef);
530-
531-
auto conformance = ProtocolConformanceRef(transportDecl);
532-
auto witness =
533-
B.createWitnessMethod(loc, openedTransport,
534-
conformance, resignFnRef,
535-
SILType::getPrimitiveObjectType(resignFnType));
536-
537-
auto subs = SubstitutionMap::getProtocolSubstitutions(transportDecl,
538-
openedTransport,
539-
conformance);
540-
541-
SmallVector<SILValue, 2> params;
542-
params.push_back(idRef.getValue());
543-
params.push_back(transportAddr); // self for the call, as last param
544-
545-
B.createApply(loc, witness, subs, params);
369+
B.createRefElementAddr(loc, actorSelf, transportVarDeclRef,
370+
getLoweredType(transportType));
371+
372+
// Perform the call.
373+
emitActorTransportWitnessCall(
374+
B, loc, ctx.Id_resignIdentity,
375+
transportRef.getValue(),
376+
SILType(),
377+
{ idRef.getValue() });
546378
}
547379

548380
void

lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2083,6 +2083,10 @@ void LifetimeChecker::handleLoadUseFailureForActorInit(
20832083
return;
20842084
}
20852085

2086+
// Skip autogenerated instructions.
2087+
if (Use.Inst->getLoc().isAutoGenerated())
2088+
return;
2089+
20862090
// Everything else is disallowed!
20872091
switch(ActorKind) {
20882092
case ActorInitKind::None:

0 commit comments

Comments
 (0)