@@ -2439,17 +2439,21 @@ class DelayedArgument {
2439
2439
2440
2440
// / A string r-value needs to be converted to a pointer type.
2441
2441
RValueStringToPointer,
2442
-
2442
+
2443
2443
// / A function conversion needs to occur.
2444
2444
FunctionConversion,
2445
-
2445
+
2446
2446
LastRVKind = FunctionConversion,
2447
-
2447
+
2448
2448
// / This is an immutable borrow from an l-value.
2449
2449
BorrowedLValue,
2450
2450
2451
2451
// / A default argument that needs to be evaluated.
2452
2452
DefaultArgument,
2453
+
2454
+ // / This is a consume of an l-value. It acts like a BorrowedLValue, but we
2455
+ // / use a deinit access scope.
2456
+ ConsumedLValue,
2453
2457
};
2454
2458
2455
2459
private:
@@ -2495,10 +2499,16 @@ class DelayedArgument {
2495
2499
ClaimedParamsRef ParamsToEmit;
2496
2500
};
2497
2501
2502
+ struct ConsumedLValueStorage {
2503
+ LValue LV;
2504
+ SILLocation Loc;
2505
+ AbstractionPattern OrigParamType;
2506
+ ClaimedParamsRef ParamsToEmit;
2507
+ };
2508
+
2498
2509
using ValueMembers =
2499
- ExternalUnionMembers<RValueStorage, LValueStorage,
2500
- DefaultArgumentStorage,
2501
- BorrowedLValueStorage>;
2510
+ ExternalUnionMembers<RValueStorage, LValueStorage, DefaultArgumentStorage,
2511
+ BorrowedLValueStorage, ConsumedLValueStorage>;
2502
2512
static ValueMembers::Index getValueMemberIndexForKind (KindTy kind) {
2503
2513
switch (kind) {
2504
2514
case InOut:
@@ -2513,6 +2523,8 @@ class DelayedArgument {
2513
2523
return ValueMembers::indexOf<DefaultArgumentStorage>();
2514
2524
case BorrowedLValue:
2515
2525
return ValueMembers::indexOf<BorrowedLValueStorage>();
2526
+ case ConsumedLValue:
2527
+ return ValueMembers::indexOf<ConsumedLValueStorage>();
2516
2528
}
2517
2529
llvm_unreachable (" bad kind" );
2518
2530
}
@@ -2586,13 +2598,18 @@ class DelayedArgument {
2586
2598
}
2587
2599
2588
2600
DelayedArgument (LValue &&lv, SILLocation loc,
2589
- AbstractionPattern origResultType,
2590
- ClaimedParamsRef params)
2591
- : Kind(BorrowedLValue) {
2592
- Value.emplaceAggregate <BorrowedLValueStorage>(Kind, std::move (lv), loc,
2593
- origResultType, params);
2601
+ AbstractionPattern origResultType, ClaimedParamsRef params,
2602
+ bool isBorrowed = true )
2603
+ : Kind(isBorrowed ? BorrowedLValue : ConsumedLValue) {
2604
+ if (isBorrowed) {
2605
+ Value.emplaceAggregate <BorrowedLValueStorage>(Kind, std::move (lv), loc,
2606
+ origResultType, params);
2607
+ } else {
2608
+ Value.emplaceAggregate <ConsumedLValueStorage>(Kind, std::move (lv), loc,
2609
+ origResultType, params);
2610
+ }
2594
2611
}
2595
-
2612
+
2596
2613
DelayedArgument (SILLocation loc,
2597
2614
ConcreteDeclRef defaultArgsOwner,
2598
2615
unsigned destIndex,
@@ -2654,6 +2671,10 @@ class DelayedArgument {
2654
2671
emitBorrowedLValue (SGF, Value.get <BorrowedLValueStorage>(Kind),
2655
2672
args, argIndex);
2656
2673
return ;
2674
+ case ConsumedLValue:
2675
+ emitConsumedLValue (SGF, Value.get <ConsumedLValueStorage>(Kind), args,
2676
+ argIndex);
2677
+ return ;
2657
2678
}
2658
2679
llvm_unreachable (" bad kind" );
2659
2680
}
@@ -2700,6 +2721,10 @@ class DelayedArgument {
2700
2721
SmallVectorImpl<ManagedValue> &args,
2701
2722
size_t &argIndex);
2702
2723
2724
+ void emitConsumedLValue (SILGenFunction &SGF, ConsumedLValueStorage &info,
2725
+ SmallVectorImpl<ManagedValue> &args,
2726
+ size_t &argIndex);
2727
+
2703
2728
// (value, owner)
2704
2729
std::pair<ManagedValue, ManagedValue>
2705
2730
finishOriginalExpr (SILGenFunction &SGF, Expr *expr) {
@@ -2741,6 +2766,7 @@ class DelayedArgument {
2741
2766
switch (Kind) {
2742
2767
case InOut:
2743
2768
case BorrowedLValue:
2769
+ case ConsumedLValue:
2744
2770
case DefaultArgument:
2745
2771
llvm_unreachable (" no original expr to finish in these cases" );
2746
2772
@@ -3184,6 +3210,13 @@ class ArgEmitter {
3184
3210
return ;
3185
3211
}
3186
3212
3213
+ if (param.isConsumed ()) {
3214
+ if (tryEmitConsumedMoveOnly (std::move (arg), loweredSubstArgType,
3215
+ loweredSubstParamType, origParamType,
3216
+ paramSlice))
3217
+ return ;
3218
+ }
3219
+
3187
3220
if (SGF.silConv .isSILIndirect (param)) {
3188
3221
emitIndirect (std::move (arg), loweredSubstArgType, origParamType, param);
3189
3222
return ;
@@ -3426,6 +3459,55 @@ class ArgEmitter {
3426
3459
origParamType, claimedParams);
3427
3460
}
3428
3461
3462
+ bool tryEmitConsumedMoveOnly (ArgumentSource &&arg,
3463
+ SILType loweredSubstArgType,
3464
+ SILType loweredSubstParamType,
3465
+ AbstractionPattern origParamType,
3466
+ ClaimedParamsRef paramsSlice) {
3467
+ assert (paramsSlice.size () == 1 );
3468
+
3469
+ // Try to find an expression we can emit as a borrowed l-value.
3470
+ auto lvExpr = std::move (arg).findStorageReferenceExprForMoveOnlyBorrow (SGF);
3471
+ if (!lvExpr)
3472
+ return false ;
3473
+
3474
+ emitConsumed (lvExpr, loweredSubstArgType, loweredSubstParamType,
3475
+ origParamType, paramsSlice);
3476
+
3477
+ return true ;
3478
+ }
3479
+
3480
+ void emitConsumed (Expr *arg, SILType loweredSubstArgType,
3481
+ SILType loweredSubstParamType,
3482
+ AbstractionPattern origParamType,
3483
+ ClaimedParamsRef claimedParams) {
3484
+ auto emissionKind = SGFAccessKind::OwnedAddressConsume;
3485
+
3486
+ LValue argLV = SGF.emitLValue (arg, emissionKind);
3487
+
3488
+ if (loweredSubstParamType.hasAbstractionDifference (Rep,
3489
+ loweredSubstArgType)) {
3490
+ argLV.addSubstToOrigComponent (origParamType, loweredSubstParamType);
3491
+ }
3492
+
3493
+ DelayedArguments.emplace_back (std::move (argLV), arg, origParamType,
3494
+ claimedParams, false /* is borrowed*/ );
3495
+ Args.push_back (ManagedValue ());
3496
+ }
3497
+
3498
+ void emitExpandedConsumed (Expr *arg, AbstractionPattern origParamType) {
3499
+ CanType substArgType = arg->getType ()->getCanonicalType ();
3500
+ auto count = getFlattenedValueCount (origParamType, substArgType);
3501
+ auto claimedParams = claimNextParameters (count);
3502
+
3503
+ SILType loweredSubstArgType = SGF.getLoweredType (substArgType);
3504
+ SILType loweredSubstParamType =
3505
+ SGF.getLoweredType (origParamType, substArgType);
3506
+
3507
+ return emitConsumed (arg, loweredSubstArgType, loweredSubstParamType,
3508
+ origParamType, claimedParams);
3509
+ }
3510
+
3429
3511
void emitDirect (ArgumentSource &&arg, SILType loweredSubstArgType,
3430
3512
AbstractionPattern origParamType,
3431
3513
SILParameterInfo param) {
@@ -3806,6 +3888,66 @@ void DelayedArgument::emitBorrowedLValue(SILGenFunction &SGF,
3806
3888
// That should drain all the parameters.
3807
3889
assert (params.empty ());
3808
3890
}
3891
+
3892
+ static void emitConsumedLValueRecursive (SILGenFunction &SGF, SILLocation loc,
3893
+ ManagedValue value,
3894
+ AbstractionPattern origParamType,
3895
+ ClaimedParamsRef ¶ms,
3896
+ MutableArrayRef<ManagedValue> args,
3897
+ size_t &argIndex) {
3898
+ // Recurse into tuples.
3899
+ if (origParamType.isTuple ()) {
3900
+ SGF.B .emitDestructureOperation (
3901
+ loc, value, [&](unsigned eltIndex, ManagedValue eltValue) {
3902
+ auto origEltType = origParamType.getTupleElementType (eltIndex);
3903
+ // Recurse.
3904
+ emitConsumedLValueRecursive (SGF, loc, eltValue, origEltType, params,
3905
+ args, argIndex);
3906
+ });
3907
+ return ;
3908
+ }
3909
+
3910
+ // Claim the next parameter.
3911
+ auto param = params.front ();
3912
+ params = params.slice (1 );
3913
+
3914
+ // Load if necessary.
3915
+ assert (param.isConsumed () && " Should have a consumed parameter?" );
3916
+ if (value.getType ().isAddress ()) {
3917
+ if (!param.isIndirectIn () || !SGF.silConv .useLoweredAddresses ()) {
3918
+ value = SGF.B .createFormalAccessLoadTake (loc, value);
3919
+ }
3920
+ }
3921
+
3922
+ assert (param.getInterfaceType () == value.getType ().getASTType ());
3923
+ args[argIndex++] = value;
3924
+ }
3925
+
3926
+ void DelayedArgument::emitConsumedLValue (SILGenFunction &SGF,
3927
+ ConsumedLValueStorage &info,
3928
+ SmallVectorImpl<ManagedValue> &args,
3929
+ size_t &argIndex) {
3930
+ // Begin the access.
3931
+ auto value = SGF.emitConsumedLValue (info.Loc , std::move (info.LV ));
3932
+ ClaimedParamsRef params = info.ParamsToEmit ;
3933
+
3934
+ // We inserted exactly one space in the argument array, so fix that up
3935
+ // to have the right number of spaces.
3936
+ if (params.size () == 0 ) {
3937
+ args.erase (args.begin () + argIndex);
3938
+ return ;
3939
+ } else if (params.size () > 1 ) {
3940
+ args.insert (args.begin () + argIndex + 1 , params.size () - 1 , ManagedValue ());
3941
+ }
3942
+
3943
+ // Recursively expand.
3944
+ emitConsumedLValueRecursive (SGF, info.Loc , value, info.OrigParamType , params,
3945
+ args, argIndex);
3946
+
3947
+ // That should drain all the parameters.
3948
+ assert (params.empty ());
3949
+ }
3950
+
3809
3951
} // end anonymous namespace
3810
3952
3811
3953
namespace {
0 commit comments