@@ -121,6 +121,16 @@ class DistributedAccessor {
121
121
const SILParameterInfo ¶m,
122
122
Explosion &arguments);
123
123
124
+ // / Load witness table addresses (if any) from the given buffer
125
+ // / into the given argument explosion.
126
+ // /
127
+ // / Number of witnesses to load is provided by \c numTables but
128
+ // / it's checked against the number of \c expectedWitnessTables.
129
+ void emitLoadOfWitnessTables (llvm::Value *witnessTables,
130
+ llvm::Value *numTables,
131
+ unsigned expectedWitnessTables,
132
+ Explosion &arguments);
133
+
124
134
FunctionPointer getPointerToTarget () const ;
125
135
126
136
Callee getCalleeForDistributedTarget (llvm::Value *self) const ;
@@ -140,6 +150,11 @@ static CanSILFunctionType getAccessorType(IRGenModule &IGM,
140
150
ParameterConvention::Direct_Guaranteed);
141
151
};
142
152
153
+ auto getUIntParameter = [&]() {
154
+ return SILParameterInfo (Context.getUIntType ()->getCanonicalType (),
155
+ ParameterConvention::Direct_Guaranteed);
156
+ };
157
+
143
158
// `self` of the distributed actor is going to be passed as an argument
144
159
// to this accessor function.
145
160
auto extInfo = SILExtInfoBuilder ()
@@ -162,6 +177,8 @@ static CanSILFunctionType getAccessorType(IRGenModule &IGM,
162
177
/* argumentTypes=*/ getRawPointerParameter (),
163
178
/* resultBuffer=*/ getRawPointerParameter (),
164
179
/* substitutions=*/ getRawPointerParameter (),
180
+ /* witnessTables=*/ getRawPointerParameter (),
181
+ /* numWitnessTables=*/ getUIntParameter (),
165
182
/* actor=*/ targetTy->getParameters ().back ()},
166
183
/* Yields=*/ {},
167
184
/* Results=*/ {},
@@ -432,6 +449,37 @@ DistributedAccessor::loadArgument(unsigned argumentIdx,
432
449
return {alignedOffset.getAddress (), typeInfo.getSize (IGF, paramTy)};
433
450
}
434
451
452
+ void DistributedAccessor::emitLoadOfWitnessTables (llvm::Value *witnessTables,
453
+ llvm::Value *numTables,
454
+ unsigned expectedWitnessTables,
455
+ Explosion &arguments) {
456
+ auto contBB = IGF.createBasicBlock (" " );
457
+ auto unreachableBB = IGF.createBasicBlock (" incorrect-witness-tables" );
458
+
459
+ auto incorrectNum = IGF.Builder .CreateICmpNE (
460
+ numTables, llvm::ConstantInt::get (IGM.SizeTy , expectedWitnessTables));
461
+
462
+ // Make sure that we have a correct number of witness tables provided to us.
463
+ IGF.Builder .CreateCondBr (incorrectNum, unreachableBB, contBB);
464
+ {
465
+ IGF.Builder .emitBlock (unreachableBB);
466
+ IGF.Builder .CreateUnreachable ();
467
+ }
468
+
469
+ IGF.Builder .emitBlock (contBB);
470
+
471
+ witnessTables = IGF.Builder .CreateBitCast (witnessTables, IGM.Int8PtrPtrTy );
472
+
473
+ for (unsigned i = 0 , n = expectedWitnessTables; i != n; ++i) {
474
+ auto offset = Size (i * IGM.getPointerSize ());
475
+ auto alignment = IGM.getPointerAlignment ();
476
+
477
+ auto witnessTableAddr = IGF.emitAddressAtOffset (
478
+ witnessTables, Offset (offset), IGM.Int8PtrTy , Alignment (alignment));
479
+ arguments.add (witnessTableAddr.getAddress ());
480
+ }
481
+ }
482
+
435
483
void DistributedAccessor::emit () {
436
484
auto targetTy = Target->getLoweredFunctionType ();
437
485
SILFunctionConventions targetConv (targetTy, IGF.getSILModule ());
@@ -457,6 +505,10 @@ void DistributedAccessor::emit() {
457
505
auto *resultBuffer = params.claimNext ();
458
506
// UnsafeRawPointer that represents a list of substitutions
459
507
auto *substitutions = params.claimNext ();
508
+ // UnsafeRawPointer that represents a list of witness tables
509
+ auto *witnessTables = params.claimNext ();
510
+ // Integer that represented the number of witness tables
511
+ auto *numWitnessTables = params.claimNext ();
460
512
// Reference to a `self` of the actor to be called.
461
513
auto *actorSelf = params.claimNext ();
462
514
@@ -490,12 +542,22 @@ void DistributedAccessor::emit() {
490
542
computeArguments (argBuffer, argTypes, arguments);
491
543
492
544
// Add all of the substitutions to the explosion
493
- if (auto *environment = Target->getGenericEnvironment ()) {
545
+ if (auto *genericEnvironment = Target->getGenericEnvironment ()) {
494
546
// swift.type **
495
547
llvm::Value *substitutionBuffer =
496
548
IGF.Builder .CreateBitCast (substitutions, IGM.TypeMetadataPtrPtrTy );
497
549
498
- for (unsigned index : indices (environment->getGenericParams ())) {
550
+ // Collect the generic arguments expected by the distributed thunk.
551
+ // We need this to determine the expected number of witness tables
552
+ // to load from the buffer provided by the caller.
553
+ llvm::SmallVector<llvm::Type *, 4 > targetGenericArguments;
554
+ expandPolymorphicSignature (IGM, targetTy, targetGenericArguments);
555
+
556
+ unsigned numGenericArgs = genericEnvironment->getGenericParams ().size ();
557
+ unsigned expectedWitnessTables =
558
+ targetGenericArguments.size () - numGenericArgs;
559
+
560
+ for (unsigned index = 0 ; index < numGenericArgs; ++index) {
499
561
auto offset =
500
562
Size (index * IGM.DataLayout .getTypeAllocSize (IGM.TypeMetadataPtrTy ));
501
563
auto alignment =
@@ -506,6 +568,9 @@ void DistributedAccessor::emit() {
506
568
IGM.TypeMetadataPtrTy , Alignment (alignment));
507
569
arguments.add (IGF.Builder .CreateLoad (substitution, " substitution" ));
508
570
}
571
+
572
+ emitLoadOfWitnessTables (witnessTables, numWitnessTables,
573
+ expectedWitnessTables, arguments);
509
574
}
510
575
511
576
// Step two, let's form and emit a call to the distributed method
0 commit comments