Skip to content

Commit 1d230ee

Browse files
ktosoxedin
authored andcommitted
[Distributed] Retain ad-hoc decodeNextArgument in distributed thunk
SIL has to force emission of `decodeNextArgument` and its retainment, so IRGen can reference it in distributed function accessor. (cherry picked from commit 79ad927) (cherry picked from commit 870c712) (cherry picked from commit dadf301) (cherry picked from commit 4e2c059) (cherry picked from commit 560e96f) (cherry picked from commit 41a4cea) (cherry picked from commit 8c8360a) (cherry picked from commit fc662bc)
1 parent d4d9c90 commit 1d230ee

24 files changed

+285
-95
lines changed

include/swift/AST/Decl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3554,10 +3554,10 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
35543554
VarDecl *getDistributedActorIDProperty() const;
35553555

35563556
/// Find the 'RemoteCallTarget.init(_:)' initializer function.
3557-
ConstructorDecl* getDistributedRemoteCallTargetInitFunction() const;
3557+
ConstructorDecl *getDistributedRemoteCallTargetInitFunction() const;
35583558

35593559
/// Find the 'RemoteCallArgument(label:name:value:)' initializer function.
3560-
ConstructorDecl* getDistributedRemoteCallArgumentInitFunction() const;
3560+
ConstructorDecl *getDistributedRemoteCallArgumentInitFunction() const;
35613561

35623562
/// Collect the set of protocols to which this type should implicitly
35633563
/// conform, such as AnyObject (for classes).

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,8 @@ ERROR(expected_sil_function_type, none,
682682
"sil function expected to have SIL function type", ())
683683
ERROR(sil_dynamically_replaced_func_not_found,none,
684684
"dynamically replaced function not found %0", (Identifier))
685+
ERROR(sil_adhoc_requirement_witness_func_not_found,none,
686+
"ad-hoc requirement witness function not found %0", (Identifier))
685687
ERROR(sil_specialize_target_func_not_found,none,
686688
"_specialize target function not found %0", (Identifier))
687689
ERROR(sil_availability_expected_version,none,

include/swift/AST/DistributedDecl.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,21 @@ Type getDistributedActorIDType(NominalTypeDecl *actor);
5353
Type getDistributedSerializationRequirementType(
5454
NominalTypeDecl *nominal, ProtocolDecl *protocol);
5555

56+
/// Given a distributed thunk declaration, inside a 'distributed actor',
57+
/// finds the ad-hoc witness for 'decodeNextArgument' on the associated
58+
/// 'ActorSystem.InvocationDecoder' of the actor, or null.
59+
AbstractFunctionDecl *
60+
getAssociatedDistributedInvocationDecoderDecodeNextArgumentFunction(
61+
ValueDecl *thunk);
62+
5663
/// Get the specific 'InvocationEncoder' type of a specific distributed actor
5764
/// system.
5865
Type getDistributedActorSystemInvocationEncoderType(NominalTypeDecl *system);
5966

67+
/// Get the specific 'InvocationDecoder' type of a specific distributed actor
68+
/// system.
69+
Type getDistributedActorSystemInvocationDecoderType(NominalTypeDecl *system);
70+
6071
/// Get the specific 'ResultHandler' type of a specific distributed actor
6172
/// system.
6273
Type getDistributedActorSystemResultHandlerType(NominalTypeDecl *system);

include/swift/SIL/SILFunction.h

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,17 @@ class SILFunction
212212
/// @_dynamicReplacement(for:) function.
213213
SILFunction *ReplacedFunction = nullptr;
214214

215+
/// This SILFunction REFerences an ad-hoc protocol requirement witness in
216+
/// order to keep it alive, such that it main be obtained in IRGen. Without
217+
/// this explicit reference, the witness would seem not-used, and not be
218+
/// accessible for IRGen.
219+
///
220+
/// Specifically, one such case is the DistributedTargetInvocationDecoder's
221+
/// 'decodeNextArgument' which must be retained, as it is only used from IRGen
222+
/// and such, appears as-if unused in SIL and would get optimized away.
223+
// TODO: Consider making this a general "references adhoc functions" and make it an array?
224+
SILFunction *RefAdHocRequirementFunction = nullptr;
225+
215226
Identifier ObjCReplacementFor;
216227

217228
/// The head of a single-linked list of currently alive BasicBlockBitfield.
@@ -298,7 +309,7 @@ class SILFunction
298309

299310
/// Whether the implementation can be dynamically replaced.
300311
unsigned IsDynamicReplaceable : 1;
301-
312+
302313
/// If true, this indicates that a class method implementation will always be
303314
/// invoked with a `self` argument of the exact base class type.
304315
unsigned ExactSelfClass : 1;
@@ -466,16 +477,6 @@ class SILFunction
466477
ReplacedFunction = f;
467478
ReplacedFunction->incrementRefCount();
468479
}
469-
470-
SILFunction *getDistributedRecordArgumentFunction() const {
471-
return ReplacedFunction;
472-
}
473-
void setDistributedRecordArgumentFunction(SILFunction *f) {
474-
if (f == nullptr)
475-
return;
476-
f->incrementRefCount();
477-
}
478-
479480
/// This function should only be called when SILFunctions are bulk deleted.
480481
void dropDynamicallyReplacedFunction() {
481482
if (!ReplacedFunction)
@@ -484,6 +485,27 @@ class SILFunction
484485
ReplacedFunction = nullptr;
485486
}
486487

488+
SILFunction *getReferencedAdHocRequirementWitnessFunction() const {
489+
return RefAdHocRequirementFunction;
490+
}
491+
// Marks that this `SILFunction` uses the passed in ad-hoc protocol
492+
// requirement witness `f` and therefore must retain it explicitly,
493+
// otherwise we might not be able to get a reference to it.
494+
void setReferencedAdHocRequirementWitnessFunction(SILFunction *f) {
495+
assert(RefAdHocRequirementFunction == nullptr && "already set");
496+
497+
if (f == nullptr)
498+
return;
499+
RefAdHocRequirementFunction = f;
500+
RefAdHocRequirementFunction->incrementRefCount();
501+
}
502+
void dropReferencedAdHocRequirementWitnessFunction() {
503+
if (!RefAdHocRequirementFunction)
504+
return;
505+
RefAdHocRequirementFunction->decrementRefCount();
506+
RefAdHocRequirementFunction = nullptr;
507+
}
508+
487509
bool hasObjCReplacement() const {
488510
return !ObjCReplacementFor.empty();
489511
}
@@ -758,7 +780,7 @@ class SILFunction
758780
IsDynamicReplaceable = value;
759781
assert(!Transparent || !IsDynamicReplaceable);
760782
}
761-
783+
762784
IsExactSelfClass_t isExactSelfClass() const {
763785
return IsExactSelfClass_t(ExactSelfClass);
764786
}

lib/AST/DistributedDecl.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ Type swift::getConcreteReplacementForProtocolActorSystemType(ValueDecl *member)
9797
}
9898

9999
Type swift::getDistributedActorSystemType(NominalTypeDecl *actor) {
100+
assert(!dyn_cast<ProtocolDecl>(actor) &&
101+
"Use getConcreteReplacementForProtocolActorSystemType instead to get"
102+
"the concrete ActorSystem, if bound, for this DistributedActor "
103+
"constrained ProtocolDecl!");
100104
assert(actor->isDistributedActor());
101105
auto &C = actor->getASTContext();
102106

@@ -168,6 +172,21 @@ Type swift::getDistributedActorSystemInvocationEncoderType(NominalTypeDecl *syst
168172
return conformance.getTypeWitnessByName(selfType, ctx.Id_InvocationEncoder);
169173
}
170174

175+
Type swift::getDistributedActorSystemInvocationDecoderType(NominalTypeDecl *system) {
176+
assert(!system->isDistributedActor());
177+
auto &ctx = system->getASTContext();
178+
179+
auto DAS = ctx.getDistributedActorSystemDecl();
180+
if (!DAS)
181+
return Type();
182+
183+
// Dig out the serialization requirement type.
184+
auto module = system->getParentModule();
185+
Type selfType = system->getSelfInterfaceType();
186+
auto conformance = module->lookupConformance(selfType, DAS);
187+
return conformance.getTypeWitnessByName(selfType, ctx.Id_InvocationDecoder);
188+
}
189+
171190
Type swift::getDistributedSerializationRequirementType(
172191
NominalTypeDecl *nominal, ProtocolDecl *protocol) {
173192
assert(nominal);
@@ -184,6 +203,32 @@ Type swift::getDistributedSerializationRequirementType(
184203
return conformance.getTypeWitnessByName(selfType, ctx.Id_SerializationRequirement);
185204
}
186205

206+
AbstractFunctionDecl *
207+
swift::getAssociatedDistributedInvocationDecoderDecodeNextArgumentFunction(
208+
ValueDecl *thunk) {
209+
assert(thunk);
210+
auto &C = thunk->getASTContext();
211+
212+
auto *actor = thunk->getDeclContext()->getSelfNominalTypeDecl();
213+
if (!actor)
214+
return nullptr;
215+
if (!actor->isDistributedActor())
216+
return nullptr;
217+
218+
auto systemTy = getConcreteReplacementForProtocolActorSystemType(thunk);
219+
if (!systemTy)
220+
return nullptr;
221+
222+
auto decoderTy =
223+
getDistributedActorSystemInvocationDecoderType(
224+
systemTy->getAnyNominal());
225+
if (!decoderTy)
226+
return nullptr;
227+
228+
return C.getDecodeNextArgumentOnDistributedInvocationDecoder(
229+
decoderTy->getAnyNominal());
230+
}
231+
187232
Type ASTContext::getAssociatedTypeOfDistributedSystemOfActor(
188233
NominalTypeDecl *actor, Identifier member) {
189234
auto &ctx = actor->getASTContext();

lib/IRGen/GenDistributed.cpp

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -813,21 +813,13 @@ ArgumentDecoderInfo DistributedAccessor::findArgumentDecoder(
813813
decoder = instance.claimNext();
814814
}
815815

816-
if (isa<StructDecl>(decoderDecl) || isa<EnumDecl>(decoderDecl) ||
817-
decoderDecl->isFinal()) {
818-
auto *decodeSIL = IGM.getSILModule().lookUpFunction(SILDeclRef(decodeFn));
819-
auto *fnPtr = IGM.getAddrOfSILFunction(decodeSIL, NotForDefinition,
820-
/*isDynamicallyReplacible=*/false);
816+
auto *decodeSIL = IGM.getSILModule().lookUpFunction(SILDeclRef(decodeFn));
817+
auto *fnPtr = IGM.getAddrOfSILFunction(decodeSIL, NotForDefinition,
818+
/*isDynamicallyReplacible=*/false);
821819

822-
auto methodPtr = FunctionPointer::forDirect(
823-
classifyFunctionPointerKind(decodeSIL), fnPtr,
824-
/*secondaryValue=*/nullptr, signature);
825-
826-
return {decoder, decoderTy, witnessTable, methodPtr, methodTy};
827-
}
828-
829-
auto methodPtr =
830-
emitVirtualMethodValue(IGF, decoderTy, SILDeclRef(decodeFn), methodTy);
820+
auto methodPtr = FunctionPointer::forDirect(
821+
classifyFunctionPointerKind(decodeSIL), fnPtr,
822+
/*secondaryValue=*/nullptr, signature);
831823

832824
return {decoder, decoderTy, witnessTable, methodPtr, methodTy};
833825
}

lib/SIL/IR/SILFunctionBuilder.cpp

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "swift/AST/AttrKind.h"
1515
#include "swift/AST/Availability.h"
1616
#include "swift/AST/DiagnosticsParse.h"
17+
#include "swift/AST/DistributedDecl.h"
1718
#include "swift/AST/Decl.h"
1819
#include "swift/AST/ParameterList.h"
1920
#include "swift/AST/SemanticAttrs.h"
@@ -200,29 +201,35 @@ void SILFunctionBuilder::addFunctionAttributes(
200201
// Only assign replacements when the thing being replaced is function-like and
201202
// explicitly declared.
202203
auto *origDecl = decl->getDynamicallyReplacedDecl();
203-
auto *replacedDecl = dyn_cast_or_null<AbstractFunctionDecl>(origDecl);
204-
if (!replacedDecl)
205-
return;
206-
207-
// For @objc method replacement we normally use categories to perform the
208-
// replacement. Except for methods in generic class where we can't. Instead,
209-
// we special case this and use the native swift replacement mechanism.
210-
if (decl->isObjC() && !decl->isNativeMethodReplacement()) {
211-
F->setObjCReplacement(replacedDecl);
212-
return;
213-
}
214-
215-
if (!constant.canBeDynamicReplacement())
216-
return;
204+
if (auto *replacedDecl = dyn_cast_or_null<AbstractFunctionDecl>(origDecl)) {
205+
// For @objc method replacement we normally use categories to perform the
206+
// replacement. Except for methods in generic class where we can't. Instead,
207+
// we special case this and use the native swift replacement mechanism.
208+
if (decl->isObjC() && !decl->isNativeMethodReplacement()) {
209+
F->setObjCReplacement(replacedDecl);
210+
return;
211+
}
217212

218-
SILDeclRef declRef(replacedDecl, constant.kind, false);
219-
auto *replacedFunc = getOrCreateDeclaration(replacedDecl, declRef);
213+
if (constant.canBeDynamicReplacement()) {
214+
SILDeclRef declRef(replacedDecl, constant.kind, false);
215+
auto *replacedFunc = getOrCreateDeclaration(replacedDecl, declRef);
220216

221-
assert(replacedFunc->getLoweredFunctionType() ==
222-
F->getLoweredFunctionType() ||
223-
replacedFunc->getLoweredFunctionType()->hasOpaqueArchetype());
217+
assert(replacedFunc->getLoweredFunctionType() ==
218+
F->getLoweredFunctionType() ||
219+
replacedFunc->getLoweredFunctionType()->hasOpaqueArchetype());
224220

225-
F->setDynamicallyReplacedFunction(replacedFunc);
221+
F->setDynamicallyReplacedFunction(replacedFunc);
222+
}
223+
} else if (constant.isDistributedThunk()) {
224+
auto decodeFuncDecl =
225+
getAssociatedDistributedInvocationDecoderDecodeNextArgumentFunction(
226+
decl);
227+
assert(decodeFuncDecl && "decodeNextArgument function not found!");
228+
229+
auto decodeRef = SILDeclRef(decodeFuncDecl);
230+
auto *adHocFunc = getOrCreateDeclaration(decodeFuncDecl, decodeRef);
231+
F->setReferencedAdHocRequirementWitnessFunction(adHocFunc);
232+
}
226233
}
227234

228235
SILFunction *SILFunctionBuilder::getOrCreateFunction(

lib/SIL/IR/SILModule.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ SILModule::~SILModule() {
138138
for (SILFunction &F : *this) {
139139
F.dropAllReferences();
140140
F.dropDynamicallyReplacedFunction();
141+
F.dropReferencedAdHocRequirementWitnessFunction();
141142
F.clearSpecializeAttrs();
142143
}
143144

@@ -467,6 +468,7 @@ void SILModule::eraseFunction(SILFunction *F) {
467468
// (References are not needed anymore.)
468469
F->clear();
469470
F->dropDynamicallyReplacedFunction();
471+
F->dropReferencedAdHocRequirementWitnessFunction();
470472
// Drop references for any _specialize(target:) functions.
471473
F->clearSpecializeAttrs();
472474
}

lib/SIL/IR/SILPrinter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2983,6 +2983,12 @@ void SILFunction::print(SILPrintContext &PrintCtx) const {
29832983
OS << "\"] ";
29842984
}
29852985

2986+
if (auto *usedFunc = getReferencedAdHocRequirementWitnessFunction()) {
2987+
OS << "[ref_adhoc_requirement_witness \"";
2988+
OS << usedFunc->getName();
2989+
OS << "\"] ";
2990+
}
2991+
29862992
if (hasObjCReplacement()) {
29872993
OS << "[objc_replacement_for \"";
29882994
OS << getObjCReplacement().str();

0 commit comments

Comments
 (0)