|
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