Skip to content

Commit b43d341

Browse files
committed
[Distributed] IRGen: Augment accessor to lookup witness tables for decode call
`decodeNextArgument` requires (at least) that argument type conform to a serialization requirement, witness table(s) for all protocol requirements have to be lookup up by accessor to form correct `decodeNextArgument` invocation.
1 parent 5a44f7f commit b43d341

File tree

1 file changed

+53
-0
lines changed

1 file changed

+53
-0
lines changed

lib/IRGen/GenDistributed.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "swift/ABI/MetadataValues.h"
3737
#include "swift/AST/ExtInfo.h"
3838
#include "swift/AST/GenericEnvironment.h"
39+
#include "swift/AST/GenericSignature.h"
3940
#include "swift/AST/ProtocolConformanceRef.h"
4041
#include "swift/IRGen/Linking.h"
4142
#include "swift/SIL/SILFunction.h"
@@ -79,6 +80,19 @@ struct ArgumentDecoderInfo {
7980

8081
CanSILFunctionType getMethodType() const { return MethodType; }
8182

83+
CanGenericSignature getGenericSignature() const {
84+
return MethodType->getInvocationGenericSignature();
85+
}
86+
87+
GenericSignature::RequiredProtocols getProtocolRequirements() const {
88+
auto signature = getGenericSignature();
89+
auto genericParams = signature.getGenericParams();
90+
91+
// func decodeNextArgument<Arg : <SerializationRequirement>() throws -> Arg
92+
assert(genericParams.size() == 1);
93+
return signature->getRequiredProtocols(genericParams.front());
94+
}
95+
8296
/// Form a callee to a decode method - `decodeNextArgument`.
8397
Callee getCallee() const;
8498
};
@@ -115,6 +129,10 @@ class DistributedAccessor {
115129
llvm::Value *argumentType, const SILParameterInfo &param,
116130
Explosion &arguments);
117131

132+
void lookupWitnessTables(llvm::Value *value,
133+
GenericSignature::RequiredProtocols protocols,
134+
Explosion &witnessTables);
135+
118136
/// Load witness table addresses (if any) from the given buffer
119137
/// into the given argument explosion.
120138
///
@@ -329,6 +347,10 @@ void DistributedAccessor::decodeArgument(unsigned argumentIdx,
329347
// substitution Argument -> <argument metadata>
330348
decodeArgs.add(argumentType);
331349

350+
// Lookup witness tables for the requirement on the argument type.
351+
lookupWitnessTables(argumentType, decoder.getProtocolRequirements(),
352+
decodeArgs);
353+
332354
Address calleeErrorSlot;
333355
llvm::Value *decodeError = nullptr;
334356

@@ -426,6 +448,37 @@ void DistributedAccessor::decodeArgument(unsigned argumentIdx,
426448
}
427449
}
428450

451+
void DistributedAccessor::lookupWitnessTables(
452+
llvm::Value *value, GenericSignature::RequiredProtocols protocols,
453+
Explosion &witnessTables) {
454+
auto conformsToProtocol = IGM.getConformsToProtocolFn();
455+
456+
for (auto *protocol : protocols) {
457+
auto *protocolDescriptor = IGM.getAddrOfProtocolDescriptor(protocol);
458+
auto *witnessTable =
459+
IGF.Builder.CreateCall(conformsToProtocol, {value, protocolDescriptor});
460+
461+
auto failBB = IGF.createBasicBlock("missing-witness");
462+
auto contBB = IGF.createBasicBlock("");
463+
464+
auto isNull = IGF.Builder.CreateICmpEQ(
465+
witnessTable, llvm::ConstantPointerNull::get(IGM.WitnessTablePtrTy));
466+
IGF.Builder.CreateCondBr(isNull, failBB, contBB);
467+
468+
// This operation shouldn't fail because runtime should have checked that
469+
// a particular argument type conforms to `SerializationRequirement`
470+
// of the distributed actor the decoder is used for. If it does fail
471+
// then accessor should trap.
472+
{
473+
IGF.Builder.emitBlock(failBB);
474+
IGF.emitTrap("missing witness table", /*EmitUnreachable=*/true);
475+
}
476+
477+
IGF.Builder.emitBlock(contBB);
478+
witnessTables.add(witnessTable);
479+
}
480+
}
481+
429482
void DistributedAccessor::emitLoadOfWitnessTables(llvm::Value *witnessTables,
430483
llvm::Value *numTables,
431484
unsigned expectedWitnessTables,

0 commit comments

Comments
 (0)