|
36 | 36 | #include "swift/ABI/MetadataValues.h"
|
37 | 37 | #include "swift/AST/ExtInfo.h"
|
38 | 38 | #include "swift/AST/GenericEnvironment.h"
|
| 39 | +#include "swift/AST/GenericSignature.h" |
39 | 40 | #include "swift/AST/ProtocolConformanceRef.h"
|
40 | 41 | #include "swift/IRGen/Linking.h"
|
41 | 42 | #include "swift/SIL/SILFunction.h"
|
@@ -79,6 +80,19 @@ struct ArgumentDecoderInfo {
|
79 | 80 |
|
80 | 81 | CanSILFunctionType getMethodType() const { return MethodType; }
|
81 | 82 |
|
| 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 | + |
82 | 96 | /// Form a callee to a decode method - `decodeNextArgument`.
|
83 | 97 | Callee getCallee() const;
|
84 | 98 | };
|
@@ -115,6 +129,10 @@ class DistributedAccessor {
|
115 | 129 | llvm::Value *argumentType, const SILParameterInfo ¶m,
|
116 | 130 | Explosion &arguments);
|
117 | 131 |
|
| 132 | + void lookupWitnessTables(llvm::Value *value, |
| 133 | + GenericSignature::RequiredProtocols protocols, |
| 134 | + Explosion &witnessTables); |
| 135 | + |
118 | 136 | /// Load witness table addresses (if any) from the given buffer
|
119 | 137 | /// into the given argument explosion.
|
120 | 138 | ///
|
@@ -329,6 +347,10 @@ void DistributedAccessor::decodeArgument(unsigned argumentIdx,
|
329 | 347 | // substitution Argument -> <argument metadata>
|
330 | 348 | decodeArgs.add(argumentType);
|
331 | 349 |
|
| 350 | + // Lookup witness tables for the requirement on the argument type. |
| 351 | + lookupWitnessTables(argumentType, decoder.getProtocolRequirements(), |
| 352 | + decodeArgs); |
| 353 | + |
332 | 354 | Address calleeErrorSlot;
|
333 | 355 | llvm::Value *decodeError = nullptr;
|
334 | 356 |
|
@@ -426,6 +448,37 @@ void DistributedAccessor::decodeArgument(unsigned argumentIdx,
|
426 | 448 | }
|
427 | 449 | }
|
428 | 450 |
|
| 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 | + |
429 | 482 | void DistributedAccessor::emitLoadOfWitnessTables(llvm::Value *witnessTables,
|
430 | 483 | llvm::Value *numTables,
|
431 | 484 | unsigned expectedWitnessTables,
|
|
0 commit comments