@@ -159,6 +159,8 @@ void ExistentialSpecializerCloner::cloneArguments(
159
159
GenericTypeParamType *GenericParam = iter->second ;
160
160
SILType GenericSILType =
161
161
NewF.getLoweredType (NewF.mapTypeIntoContext (GenericParam));
162
+ GenericSILType = GenericSILType.getCategoryType (
163
+ ArgDesc.Arg ->getType ().getCategory ());
162
164
auto *NewArg = ClonedEntryBB->createFunctionArgument (GenericSILType);
163
165
NewArg->setOwnershipKind (ValueOwnershipKind (
164
166
NewF, GenericSILType, ArgDesc.Arg ->getArgumentConvention ()));
@@ -173,6 +175,7 @@ void ExistentialSpecializerCloner::cloneArguments(
173
175
Ctx.AllocateCopy (NewConformances);
174
176
auto ExistentialRepr =
175
177
ArgDesc.Arg ->getType ().getPreferredExistentialRepresentation (M);
178
+ auto &EAD = ExistentialArgDescriptor[ArgDesc.Index ];
176
179
switch (ExistentialRepr) {
177
180
case ExistentialRepresentation::Opaque: {
178
181
// / Create this sequence for init_existential_addr.:
@@ -190,7 +193,7 @@ void ExistentialSpecializerCloner::cloneArguments(
190
193
InsertLoc, ASI, NewArg->getType ().getASTType (), NewArg->getType (),
191
194
Conformances);
192
195
193
- bool origConsumed = ExistentialArgDescriptor[ArgDesc. Index ] .isConsumed ;
196
+ bool origConsumed = EAD .isConsumed ;
194
197
// If the existential is not consumed in the function body, then the one
195
198
// we introduce here needs cleanup.
196
199
if (!origConsumed)
@@ -204,16 +207,32 @@ void ExistentialSpecializerCloner::cloneArguments(
204
207
break ;
205
208
}
206
209
case ExistentialRepresentation::Class: {
210
+ SILValue NewArgValue = NewArg;
211
+ if (!NewArg->getType ().isObject ()) {
212
+ NewArgValue = NewFBuilder.createLoad (InsertLoc, NewArg,
213
+ LoadOwnershipQualifier::Unqualified);
214
+ }
215
+
207
216
// FIXME_ownership: init_existential_ref always takes ownership of the
208
217
// incoming reference. If the argument convention is borrowed
209
218
// (!isConsumed), then we should create a copy_value here and add this new
210
219
// existential to the CleanupValues vector.
211
220
212
221
// / Simple case: Create an init_existential.
213
222
// / %5 = init_existential_ref %0 : $T : $T, $P
214
- auto *InitRef = NewFBuilder.createInitExistentialRef (
215
- InsertLoc, ArgDesc.Arg ->getType (), NewArg->getType ().getASTType (),
216
- NewArg, Conformances);
223
+ SILValue InitRef = NewFBuilder.createInitExistentialRef (
224
+ InsertLoc, ArgDesc.Arg ->getType ().getObjectType (),
225
+ NewArg->getType ().getASTType (),
226
+ NewArgValue, Conformances);
227
+
228
+ if (!NewArg->getType ().isObject ()) {
229
+ auto alloc = NewFBuilder.createAllocStack (InsertLoc,
230
+ InitRef->getType ());
231
+ NewFBuilder.createStore (InsertLoc, InitRef, alloc,
232
+ StoreOwnershipQualifier::Unqualified);
233
+ InitRef = alloc;
234
+ AllocStackInsts.push_back (alloc);
235
+ }
217
236
218
237
entryArgs.push_back (InitRef);
219
238
break ;
@@ -369,7 +388,8 @@ void ExistentialTransform::populateThunkBody() {
369
388
// / Create a basic block and the function arguments.
370
389
auto *ThunkBody = F->createBasicBlock ();
371
390
for (auto &ArgDesc : ArgumentDescList) {
372
- ThunkBody->createFunctionArgument (ArgDesc.Arg ->getType (), ArgDesc.Decl );
391
+ auto argumentType = ArgDesc.Arg ->getType ();
392
+ ThunkBody->createFunctionArgument (argumentType, ArgDesc.Decl );
373
393
}
374
394
375
395
// / Builder to add new instructions in the Thunk.
@@ -394,7 +414,11 @@ void ExistentialTransform::populateThunkBody() {
394
414
SmallVector<SILValue, 8 > ApplyArgs;
395
415
// Maintain a list of arg values to be destroyed. These are consumed by the
396
416
// convention and require a copy.
397
- SmallVector<CopyAddrInst *, 8 > TempCopyAddrInsts;
417
+ struct Temp {
418
+ SILValue DeallocStackEntry;
419
+ SILValue DestroyValue;
420
+ };
421
+ SmallVector<Temp, 8 > Temps;
398
422
SmallDenseMap<GenericTypeParamType *, Type> GenericToOpenedTypeMap;
399
423
for (auto &ArgDesc : ArgumentDescList) {
400
424
auto iter = ArgToGenericTypeMap.find (ArgDesc.Index );
@@ -422,22 +446,32 @@ void ExistentialTransform::populateThunkBody() {
422
446
// must pass in a copy.
423
447
auto *ASI =
424
448
Builder.createAllocStack (Loc, OpenedSILType);
425
- auto *CAI =
426
- Builder.createCopyAddr (Loc, archetypeValue, ASI, IsNotTake,
427
- IsInitialization_t::IsInitialization);
428
- TempCopyAddrInsts.push_back (CAI);
449
+ Builder.createCopyAddr (Loc, archetypeValue, ASI, IsNotTake,
450
+ IsInitialization_t::IsInitialization);
451
+ Temps.push_back ({ASI, OrigOperand});
429
452
calleeArg = ASI;
430
453
}
431
454
ApplyArgs.push_back (calleeArg);
432
455
break ;
433
456
}
434
457
case ExistentialRepresentation::Class: {
435
- // / If the operand is not object type, we would need an explicit load.
458
+ // If the operand is not object type, we need an explicit load.
459
+ SILValue OrigValue = OrigOperand;
460
+ if (!OrigOperand->getType ().isObject ()) {
461
+ OrigValue = Builder.createLoad (Loc, OrigValue,
462
+ LoadOwnershipQualifier::Unqualified);
463
+ }
436
464
// OpenExistentialRef forwards ownership, so it does the right thing
437
465
// regardless of whether the argument is borrowed or consumed.
438
- assert (OrigOperand->getType ().isObject ());
439
466
archetypeValue =
440
- Builder.createOpenExistentialRef (Loc, OrigOperand, OpenedSILType);
467
+ Builder.createOpenExistentialRef (Loc, OrigValue, OpenedSILType);
468
+ if (!OrigOperand->getType ().isObject ()) {
469
+ SILValue ASI = Builder.createAllocStack (Loc, OpenedSILType);
470
+ Builder.createStore (Loc, archetypeValue, ASI,
471
+ StoreOwnershipQualifier::Unqualified);
472
+ Temps.push_back ({ASI, SILValue ()});
473
+ archetypeValue = ASI;
474
+ }
441
475
ApplyArgs.push_back (archetypeValue);
442
476
break ;
443
477
}
@@ -511,7 +545,7 @@ void ExistentialTransform::populateThunkBody() {
511
545
ReturnValue = Builder.createApply (Loc, FRI, SubMap, ApplyArgs);
512
546
}
513
547
auto cleanupLoc = RegularLocation::getAutoGeneratedLocation ();
514
- for (CopyAddrInst *CAI : reversed (TempCopyAddrInsts )) {
548
+ for (auto &Temp : reversed (Temps )) {
515
549
// The original argument was copied into a temporary and consumed by the
516
550
// callee as such:
517
551
// bb (%consumedExistential : $*Protocol)
@@ -523,10 +557,10 @@ void ExistentialTransform::populateThunkBody() {
523
557
// Destroy the original arument and deallocation the temporary:
524
558
// destroy_addr %consumedExistential : $*Protocol
525
559
// dealloc_stack %temp : $*T
526
- auto *consumedExistential = cast<SILFunctionArgument>(
527
- cast<OpenExistentialAddrInst>(CAI-> getSrc ())-> getOperand () );
528
- Builder. createDestroyAddr (cleanupLoc, consumedExistential);
529
- Builder.createDeallocStack (cleanupLoc, CAI-> getDest () );
560
+ if (Temp. DestroyValue )
561
+ Builder. createDestroyAddr (cleanupLoc, Temp. DestroyValue );
562
+ if (Temp. DeallocStackEntry )
563
+ Builder.createDeallocStack (cleanupLoc, Temp. DeallocStackEntry );
530
564
}
531
565
// / Set up the return results.
532
566
if (NewF->isNoReturnFunction ()) {
0 commit comments