@@ -3407,3 +3407,148 @@ void SILGenFunction::emitProtocolWitness(Type selfType,
3407
3407
scope.pop ();
3408
3408
B.createReturn (loc, reqtResultValue);
3409
3409
}
3410
+
3411
+ // ===----------------------------------------------------------------------===//
3412
+ // Conversion to Canonical SILFunctionType Thunks
3413
+ // ===----------------------------------------------------------------------===//
3414
+
3415
+ static void translateParametersForCanonicalFunctionThunk (
3416
+ SILGenFunction &SGF, SILLocation loc,
3417
+ ArrayRef<ManagedValue> origParamValues,
3418
+ ArrayRef<SILParameterInfo> newParamInfos,
3419
+ SmallVectorImpl<ManagedValue> &newParams) {
3420
+ assert (origParamValues.size () == newParamInfos.size ());
3421
+
3422
+ for (auto T : llvm::zip (origParamValues, newParamInfos)) {
3423
+ ManagedValue origParam;
3424
+ SILParameterInfo newParamInfo;
3425
+ std::tie (origParam, newParamInfo) = T;
3426
+
3427
+ if (origParam.getType ().isTrivial (SGF.getModule ())) {
3428
+ newParams.emplace_back (origParam);
3429
+ continue ;
3430
+ }
3431
+
3432
+ if (origParam.hasCleanup ()) {
3433
+ // If we have a +1 value and the non-canonical function expects a
3434
+ // guaranteed parameter, borrow the parameter. Otherwise just pass off the
3435
+ // +1 value.
3436
+ if (newParamInfo.isGuaranteed ()) {
3437
+ origParam = origParam.borrow (SGF, loc);
3438
+ }
3439
+ newParams.emplace_back (origParam);
3440
+ continue ;
3441
+ }
3442
+
3443
+ // Otherwise, if we have a +0 value and we want to pass it off as a +1
3444
+ // value, perform the copy.
3445
+ if (newParamInfo.isConsumed ()) {
3446
+ origParam = origParam.copy (SGF, loc);
3447
+ }
3448
+ newParams.emplace_back (origParam);
3449
+ }
3450
+ }
3451
+
3452
+ static void buildCanonicalFunctionThunkBody (SILGenFunction &SGF,
3453
+ SILLocation loc,
3454
+ CanSILFunctionType nonCanonicalTy,
3455
+ CanSILFunctionType canonicalTy) {
3456
+ SGF.F .setBare (IsBare);
3457
+ SGF.F .setThunk (IsThunk);
3458
+
3459
+ FullExpr scope (SGF.Cleanups , CleanupLocation::get (loc));
3460
+ FormalEvaluationScope formalEvalScope (SGF);
3461
+
3462
+ // Collect the thunk params, creating arguments for each parameter.
3463
+ SmallVector<ManagedValue, 8 > origParams;
3464
+ SGF.collectThunkParams (loc, origParams);
3465
+
3466
+ // Then translate our parameters into new params.
3467
+ SmallVector<ManagedValue, 8 > newParams;
3468
+ translateParametersForCanonicalFunctionThunk (
3469
+ SGF, loc,
3470
+ // We drop the front so we don't process the thunked function here. We
3471
+ // handle that later.
3472
+ llvm::makeArrayRef (origParams).drop_back (1 ),
3473
+ nonCanonicalTy->getParameters (), newParams);
3474
+
3475
+ // Then grab the function we are going to call from the last parameter.
3476
+ ManagedValue fn = origParams.back ();
3477
+
3478
+ // Collect the arguments.
3479
+ SmallVector<SILValue, 8 > args;
3480
+
3481
+ // Add all of the indirect results. We can just add the SILValues directly to
3482
+ // the args array since we do not need to perform any transformations upon
3483
+ // them because:
3484
+ //
3485
+ // 1. Reabstraction can not occur as a result of a canonical/non-canonical
3486
+ // mismatch.
3487
+ // 2. SILGenFunction::collectThunkParams(...) does not create cleanups when it
3488
+ // creates arguments.
3489
+ SILFunctionConventions fnConv (canonicalTy, SGF.SGM .M );
3490
+ transform (range (fnConv.getNumIndirectSILResults ()), std::back_inserter (args),
3491
+ [&](unsigned Index) -> SILValue {
3492
+ return SGF.F .begin ()->getArgument (Index);
3493
+ });
3494
+
3495
+ // and then the rest of the arguments besides the first argument. Here we have
3496
+ // to forward the arguments since collectThunkParams /does/ create cleanups
3497
+ // for the parameters.
3498
+ forwardFunctionArguments (SGF, loc, nonCanonicalTy, newParams, args);
3499
+
3500
+ // Perform the call.
3501
+ SILValue result =
3502
+ SGF.emitApplyWithRethrow (loc, fn.forward (SGF), fn.getType (), {}, args);
3503
+
3504
+ formalEvalScope.pop ();
3505
+ scope.pop ();
3506
+ SGF.B .createReturn (loc, result);
3507
+ }
3508
+
3509
+ ManagedValue
3510
+ SILGenFunction::emitCanonicalFunctionThunk (SILLocation loc, ManagedValue fn,
3511
+ CanSILFunctionType nonCanonicalTy,
3512
+ CanSILFunctionType canonicalTy) {
3513
+ canonicalTy = canonicalTy->getWithRepresentation (
3514
+ SILFunctionType::Representation::Thick);
3515
+
3516
+ SubstitutionMap contextSubs, interfaceSubs;
3517
+ GenericEnvironment *genericEnv = nullptr ;
3518
+
3519
+ // These two are not used here -- but really, bridging thunks
3520
+ // should be emitted using the formal AST type, not the lowered
3521
+ // type
3522
+ CanType inputSubstType;
3523
+ CanType outputSubstType;
3524
+ auto thunkTy = buildThunkType (nonCanonicalTy, canonicalTy, inputSubstType,
3525
+ outputSubstType, genericEnv, interfaceSubs);
3526
+ auto thunk = SGM.getOrCreateReabstractionThunk (thunkTy, nonCanonicalTy,
3527
+ canonicalTy, F.isSerialized ());
3528
+ if (thunk->empty ()) {
3529
+ thunk->setGenericEnvironment (genericEnv);
3530
+ SILGenFunction thunkSGF (SGM, *thunk);
3531
+ auto loc = RegularLocation::getAutoGeneratedLocation ();
3532
+ buildCanonicalFunctionThunkBody (thunkSGF, loc, nonCanonicalTy, canonicalTy);
3533
+ }
3534
+
3535
+ CanSILFunctionType substFnTy = thunkTy;
3536
+
3537
+ SmallVector<Substitution, 4 > subs;
3538
+ if (auto genericSig = thunkTy->getGenericSignature ()) {
3539
+ genericSig->getSubstitutions (interfaceSubs, subs);
3540
+ substFnTy = thunkTy->substGenericArgs (F.getModule (), interfaceSubs);
3541
+ }
3542
+
3543
+ // Create it in the current function.
3544
+ auto thunkValue = B.createFunctionRef (loc, thunk);
3545
+ ManagedValue thunkedFn = B.createPartialApply (
3546
+ loc, thunkValue, SILType::getPrimitiveObjectType (substFnTy), subs, {fn},
3547
+ SILType::getPrimitiveObjectType (canonicalTy));
3548
+ if (canonicalTy->isNoEscape ()) {
3549
+ auto &funcTL = getTypeLowering (canonicalTy);
3550
+ thunkedFn =
3551
+ B.createConvertFunction (loc, thunkedFn, funcTL.getLoweredType ());
3552
+ }
3553
+ return thunkedFn;
3554
+ }
0 commit comments