Skip to content

Commit 675441d

Browse files
xedinktoso
authored andcommitted
[IRGen] Implement dynamic witness table lookup for Res of DistributedActorSystem.remoteCall witnesses
When IRGen is building a protocol witness thunk for a `DistributedActorSystem.remoteCall` requirement we need to supply witness tables associated with `Res` generic parameter which are not expressible on the requirement because they come from `SerializationRequirement` associated type.
1 parent 8223abe commit 675441d

File tree

1 file changed

+45
-0
lines changed

1 file changed

+45
-0
lines changed

lib/IRGen/GenProto.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,14 @@ class EmitPolymorphicParameters : public PolymorphicConvention {
547547
// Did the convention decide that the parameter at the given index
548548
// was a class-pointer source?
549549
bool isClassPointerSource(unsigned paramIndex);
550+
551+
// If we are building a protocol witness thunk for a
552+
// `DistributedActorSystem.remoteCall` requirement we
553+
// need to supply witness tables associated with `Res`
554+
// generic parameter which are not expressible on the
555+
// requirement because they come from `SerializationRequirement`
556+
// associated type.
557+
void injectAdHocDistributedRemoteCallRequirements();
550558
};
551559

552560
} // end anonymous namespace
@@ -722,6 +730,40 @@ bool EmitPolymorphicParameters::isClassPointerSource(unsigned paramIndex) {
722730
return false;
723731
}
724732

733+
void EmitPolymorphicParameters::injectAdHocDistributedRemoteCallRequirements() {
734+
// FIXME: We need a better way to recognize that function is
735+
// a thunk for witness of `remoteCall` requirement.
736+
if (!Fn.hasLocation())
737+
return;
738+
739+
auto loc = Fn.getLocation();
740+
741+
auto *funcDecl = dyn_cast_or_null<FuncDecl>(loc.getAsDeclContext());
742+
if (!(funcDecl && funcDecl->isDistributedActorSystemRemoteCall(
743+
/*isVoidReturn=*/false)))
744+
return;
745+
746+
auto sig = funcDecl->getGenericSignature();
747+
auto resultInterfaceTy = funcDecl->getResultInterfaceType();
748+
auto resultArchetypeTy =
749+
getTypeInContext(resultInterfaceTy->getCanonicalType());
750+
llvm::Value *resultMetadata = IGF.emitTypeMetadataRef(resultArchetypeTy);
751+
752+
auto resultRequirements = sig->getLocalRequirements(resultInterfaceTy);
753+
for (auto *proto : resultRequirements.protos) {
754+
// Lookup the witness table for this protocol dynamically via
755+
// swift_conformsToProtocol(<<archetype>>, <<protocol>>)
756+
auto *witnessTable = IGF.Builder.CreateCall(
757+
IGM.getConformsToProtocolFunctionPointer(),
758+
{resultMetadata, IGM.getAddrOfProtocolDescriptor(proto)});
759+
760+
IGF.setUnscopedLocalTypeData(
761+
resultArchetypeTy,
762+
LocalTypeDataKind::forAbstractProtocolWitnessTable(proto),
763+
witnessTable);
764+
}
765+
}
766+
725767
namespace {
726768

727769
/// A class for binding type parameters of a generic function.
@@ -2574,6 +2616,9 @@ void EmitPolymorphicParameters::emit(EntryPointArgumentEmission &emission,
25742616

25752617
// Bind all the fulfillments we can from the formal parameters.
25762618
bindParameterSources(getParameter);
2619+
2620+
// Inject ad-hoc `remoteCall` requirements if any.
2621+
injectAdHocDistributedRemoteCallRequirements();
25772622
}
25782623

25792624
MetadataResponse

0 commit comments

Comments
 (0)