@@ -249,6 +249,58 @@ CanSILFunctionType buildThunkType(SILFunction *fn,
249
249
fn->getASTContext ());
250
250
}
251
251
252
+ // / Forward function arguments, handling ownership convention mismatches.
253
+ // / Adapted from `forwardFunctionArguments` in SILGenPoly.cpp.
254
+ // /
255
+ // / Forwarded arguments are appended to `forwardedArgs`.
256
+ // /
257
+ // / Local allocations are appended to `localAllocations`. They need to be
258
+ // / deallocated via `dealloc_stack`.
259
+ // /
260
+ // / Local values requiring cleanup are appended to `valuesToCleanup`.
261
+ static void forwardFunctionArgumentsConvertingOwnership (
262
+ SILBuilder &builder, SILLocation loc, CanSILFunctionType fromTy,
263
+ CanSILFunctionType toTy, ArrayRef<SILArgument *> originalArgs,
264
+ SmallVectorImpl<SILValue> &forwardedArgs,
265
+ SmallVectorImpl<AllocStackInst *> &localAllocations,
266
+ SmallVectorImpl<SILValue> &valuesToCleanup) {
267
+ auto fromParameters = fromTy->getParameters ();
268
+ auto toParameters = toTy->getParameters ();
269
+ assert (fromParameters.size () == toParameters.size ());
270
+ assert (fromParameters.size () == originalArgs.size ());
271
+ for (auto index : indices (originalArgs)) {
272
+ auto &arg = originalArgs[index];
273
+ auto fromParam = fromParameters[index];
274
+ auto toParam = toParameters[index];
275
+ // To convert guaranteed argument to be owned, create a copy.
276
+ if (fromParam.isConsumed () && !toParam.isConsumed ()) {
277
+ // If the argument has an object type, create a `copy_value`.
278
+ if (arg->getType ().isObject ()) {
279
+ auto argCopy = builder.emitCopyValueOperation (loc, arg);
280
+ forwardedArgs.push_back (argCopy);
281
+ continue ;
282
+ }
283
+ // If the argument has an address type, create a local allocation and
284
+ // `copy_addr` its contents to the local allocation.
285
+ auto *alloc = builder.createAllocStack (loc, arg->getType ());
286
+ builder.createCopyAddr (loc, arg, alloc, IsNotTake, IsInitialization);
287
+ localAllocations.push_back (alloc);
288
+ forwardedArgs.push_back (alloc);
289
+ continue ;
290
+ }
291
+ // To convert owned argument to be guaranteed, borrow the argument.
292
+ if (fromParam.isGuaranteed () && !toParam.isGuaranteed ()) {
293
+ auto bbi = builder.emitBeginBorrowOperation (loc, arg);
294
+ forwardedArgs.push_back (bbi);
295
+ valuesToCleanup.push_back (bbi);
296
+ valuesToCleanup.push_back (arg);
297
+ continue ;
298
+ }
299
+ // Otherwise, simply forward the argument.
300
+ forwardedArgs.push_back (arg);
301
+ }
302
+ }
303
+
252
304
SILFunction *getOrCreateReabstractionThunk (SILOptFunctionBuilder &fb,
253
305
SILModule &module , SILLocation loc,
254
306
SILFunction *caller,
@@ -274,18 +326,13 @@ SILFunction *getOrCreateReabstractionThunk(SILOptFunctionBuilder &fb,
274
326
thunkType, fromInterfaceType, toInterfaceType, Type (),
275
327
module .getSwiftModule ());
276
328
277
- // FIXME(TF-989): Mark reabstraction thunks as transparent. This requires
278
- // generating ossa reabstraction thunks so that they can be inlined during
279
- // mandatory inlining when `-enable-strip-ownership-after-serialization` is
280
- // true and ownership model eliminator is not run after differentiation.
281
329
auto *thunk = fb.getOrCreateSharedFunction (
282
- loc, name, thunkDeclType, IsBare, IsNotTransparent , IsSerialized,
330
+ loc, name, thunkDeclType, IsBare, IsTransparent , IsSerialized,
283
331
ProfileCounter (), IsReabstractionThunk, IsNotDynamic);
284
332
if (!thunk->empty ())
285
333
return thunk;
286
334
287
335
thunk->setGenericEnvironment (genericEnv);
288
- thunk->setOwnershipEliminated ();
289
336
auto *entry = thunk->createBasicBlock ();
290
337
SILBuilder builder (entry);
291
338
createEntryArguments (thunk);
@@ -294,13 +341,21 @@ SILFunction *getOrCreateReabstractionThunk(SILOptFunctionBuilder &fb,
294
341
SILFunctionConventions toConv (toType, module );
295
342
assert (toConv.useLoweredAddresses ());
296
343
297
- auto *fnArg = thunk->getArgumentsWithoutIndirectResults ().back ();
344
+ // Forward thunk arguments, handling ownership convention mismatches.
345
+ SmallVector<SILValue, 4 > forwardedArgs;
346
+ for (auto indRes : thunk->getIndirectResults ())
347
+ forwardedArgs.push_back (indRes);
348
+ SmallVector<AllocStackInst *, 4 > localAllocations;
349
+ SmallVector<SILValue, 4 > valuesToCleanup;
350
+ forwardFunctionArgumentsConvertingOwnership (
351
+ builder, loc, fromType, toType,
352
+ thunk->getArgumentsWithoutIndirectResults ().drop_back (), forwardedArgs,
353
+ localAllocations, valuesToCleanup);
298
354
299
355
SmallVector<SILValue, 4 > arguments;
300
- auto toArgIter = thunk-> getArguments () .begin ();
356
+ auto toArgIter = forwardedArgs .begin ();
301
357
auto useNextArgument = [&]() { arguments.push_back (*toArgIter++); };
302
358
303
- SmallVector<AllocStackInst *, 4 > localAllocations;
304
359
auto createAllocStack = [&](SILType type) {
305
360
auto *alloc = builder.createAllocStack (loc, type);
306
361
localAllocations.push_back (alloc);
@@ -350,21 +405,25 @@ SILFunction *getOrCreateReabstractionThunk(SILOptFunctionBuilder &fb,
350
405
if (!paramTy.hasArchetype ())
351
406
paramTy = thunk->mapTypeIntoContext (paramTy);
352
407
assert (paramTy.isAddress ());
353
- auto * toArg = *toArgIter++;
408
+ auto toArg = *toArgIter++;
354
409
auto *buf = createAllocStack (toArg->getType ());
355
- builder.createStore (loc, toArg, buf,
356
- StoreOwnershipQualifier::Unqualified);
410
+ toArg = builder.emitCopyValueOperation (loc, toArg);
411
+ builder.emitStoreValueOperation (loc, toArg, buf,
412
+ StoreOwnershipQualifier::Init);
413
+ valuesToCleanup.push_back (buf);
357
414
arguments.push_back (buf);
358
415
continue ;
359
416
}
360
417
// Convert direct parameter to indirect parameter.
361
418
assert (toParam.isFormalIndirect ());
362
- auto *toArg = *toArgIter++;
363
- auto *load =
364
- builder.createLoad (loc, toArg, LoadOwnershipQualifier::Unqualified);
419
+ auto toArg = *toArgIter++;
420
+ auto load = builder.emitLoadBorrowOperation (loc, toArg);
421
+ if (isa<LoadBorrowInst>(load))
422
+ valuesToCleanup.push_back (load);
365
423
arguments.push_back (load);
366
424
}
367
425
426
+ auto *fnArg = thunk->getArgumentsWithoutIndirectResults ().back ();
368
427
auto *apply = builder.createApply (loc, fnArg, SubstitutionMap (), arguments,
369
428
/* isNonThrowing*/ false );
370
429
@@ -413,8 +472,8 @@ SILFunction *getOrCreateReabstractionThunk(SILOptFunctionBuilder &fb,
413
472
// Load direct results from indirect results.
414
473
if (fromRes.isFormalIndirect ()) {
415
474
auto indRes = *fromIndResultsIter++;
416
- auto * load =
417
- builder. createLoad (loc, indRes, LoadOwnershipQualifier::Unqualified );
475
+ auto load = builder. emitLoadValueOperation (loc, indRes,
476
+ LoadOwnershipQualifier::Take );
418
477
results.push_back (load);
419
478
continue ;
420
479
}
@@ -426,11 +485,28 @@ SILFunction *getOrCreateReabstractionThunk(SILOptFunctionBuilder &fb,
426
485
assert (resultTy.isAddress ());
427
486
#endif
428
487
auto indRes = *toIndResultsIter++;
429
- builder.createStore (loc, *fromDirResultsIter++, indRes,
430
- StoreOwnershipQualifier::Unqualified);
488
+ auto dirRes = *fromDirResultsIter++;
489
+ builder.emitStoreValueOperation (loc, dirRes, indRes,
490
+ StoreOwnershipQualifier::Init);
431
491
}
432
492
auto retVal = joinElements (results, builder, loc);
433
493
494
+ // Clean up local values.
495
+ // Guaranteed values need an `end_borrow`.
496
+ // Owned values need to be destroyed.
497
+ for (auto arg : valuesToCleanup) {
498
+ switch (arg.getOwnershipKind ()) {
499
+ case ValueOwnershipKind::Guaranteed:
500
+ builder.emitEndBorrowOperation (loc, arg);
501
+ break ;
502
+ case ValueOwnershipKind::Owned:
503
+ case ValueOwnershipKind::Unowned:
504
+ case ValueOwnershipKind::None:
505
+ builder.emitDestroyOperation (loc, arg);
506
+ break ;
507
+ }
508
+ }
509
+
434
510
// Deallocate local allocations.
435
511
for (auto *alloc : llvm::reverse (localAllocations))
436
512
builder.createDeallocStack (loc, alloc);
@@ -549,11 +625,11 @@ getOrCreateSubsetParametersThunkForLinearMap(
549
625
auto *buf = builder.createAllocStack (loc, zeroSILObjType);
550
626
localAllocations.push_back (buf);
551
627
emitZeroIntoBuffer (builder, zeroType, buf, loc);
552
- if (zeroSILType.isAddress ())
628
+ if (zeroSILType.isAddress ()) {
553
629
arguments.push_back (buf);
554
- else {
555
- auto * arg =
556
- builder. createLoad (loc, buf, LoadOwnershipQualifier::Unqualified );
630
+ } else {
631
+ auto arg = builder. emitLoadValueOperation (loc, buf,
632
+ LoadOwnershipQualifier::Take );
557
633
arguments.push_back (arg);
558
634
}
559
635
break ;
@@ -810,8 +886,6 @@ getOrCreateSubsetParametersThunkForDerivativeFunction(
810
886
if (!thunk->empty ())
811
887
return {thunk, interfaceSubs};
812
888
813
- // TODO(TF-1206): Enable ownership in all differentiation thunks.
814
- thunk->setOwnershipEliminated ();
815
889
thunk->setGenericEnvironment (genericEnv);
816
890
auto *entry = thunk->createBasicBlock ();
817
891
SILBuilder builder (entry);
0 commit comments