@@ -2439,17 +2439,21 @@ class DelayedArgument {
24392439
24402440 // / A string r-value needs to be converted to a pointer type.
24412441 RValueStringToPointer,
2442-
2442+
24432443 // / A function conversion needs to occur.
24442444 FunctionConversion,
2445-
2445+
24462446 LastRVKind = FunctionConversion,
2447-
2447+
24482448 // / This is an immutable borrow from an l-value.
24492449 BorrowedLValue,
24502450
24512451 // / A default argument that needs to be evaluated.
24522452 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,
24532457 };
24542458
24552459private:
@@ -2495,10 +2499,16 @@ class DelayedArgument {
24952499 ClaimedParamsRef ParamsToEmit;
24962500 };
24972501
2502+ struct ConsumedLValueStorage {
2503+ LValue LV;
2504+ SILLocation Loc;
2505+ AbstractionPattern OrigParamType;
2506+ ClaimedParamsRef ParamsToEmit;
2507+ };
2508+
24982509 using ValueMembers =
2499- ExternalUnionMembers<RValueStorage, LValueStorage,
2500- DefaultArgumentStorage,
2501- BorrowedLValueStorage>;
2510+ ExternalUnionMembers<RValueStorage, LValueStorage, DefaultArgumentStorage,
2511+ BorrowedLValueStorage, ConsumedLValueStorage>;
25022512 static ValueMembers::Index getValueMemberIndexForKind (KindTy kind) {
25032513 switch (kind) {
25042514 case InOut:
@@ -2513,6 +2523,8 @@ class DelayedArgument {
25132523 return ValueMembers::indexOf<DefaultArgumentStorage>();
25142524 case BorrowedLValue:
25152525 return ValueMembers::indexOf<BorrowedLValueStorage>();
2526+ case ConsumedLValue:
2527+ return ValueMembers::indexOf<ConsumedLValueStorage>();
25162528 }
25172529 llvm_unreachable (" bad kind" );
25182530 }
@@ -2586,13 +2598,18 @@ class DelayedArgument {
25862598 }
25872599
25882600 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+ }
25942611 }
2595-
2612+
25962613 DelayedArgument (SILLocation loc,
25972614 ConcreteDeclRef defaultArgsOwner,
25982615 unsigned destIndex,
@@ -2654,6 +2671,10 @@ class DelayedArgument {
26542671 emitBorrowedLValue (SGF, Value.get <BorrowedLValueStorage>(Kind),
26552672 args, argIndex);
26562673 return ;
2674+ case ConsumedLValue:
2675+ emitConsumedLValue (SGF, Value.get <ConsumedLValueStorage>(Kind), args,
2676+ argIndex);
2677+ return ;
26572678 }
26582679 llvm_unreachable (" bad kind" );
26592680 }
@@ -2700,6 +2721,10 @@ class DelayedArgument {
27002721 SmallVectorImpl<ManagedValue> &args,
27012722 size_t &argIndex);
27022723
2724+ void emitConsumedLValue (SILGenFunction &SGF, ConsumedLValueStorage &info,
2725+ SmallVectorImpl<ManagedValue> &args,
2726+ size_t &argIndex);
2727+
27032728 // (value, owner)
27042729 std::pair<ManagedValue, ManagedValue>
27052730 finishOriginalExpr (SILGenFunction &SGF, Expr *expr) {
@@ -2741,6 +2766,7 @@ class DelayedArgument {
27412766 switch (Kind) {
27422767 case InOut:
27432768 case BorrowedLValue:
2769+ case ConsumedLValue:
27442770 case DefaultArgument:
27452771 llvm_unreachable (" no original expr to finish in these cases" );
27462772
@@ -3184,6 +3210,13 @@ class ArgEmitter {
31843210 return ;
31853211 }
31863212
3213+ if (param.isConsumed ()) {
3214+ if (tryEmitConsumedMoveOnly (std::move (arg), loweredSubstArgType,
3215+ loweredSubstParamType, origParamType,
3216+ paramSlice))
3217+ return ;
3218+ }
3219+
31873220 if (SGF.silConv .isSILIndirect (param)) {
31883221 emitIndirect (std::move (arg), loweredSubstArgType, origParamType, param);
31893222 return ;
@@ -3426,6 +3459,55 @@ class ArgEmitter {
34263459 origParamType, claimedParams);
34273460 }
34283461
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+
34293511 void emitDirect (ArgumentSource &&arg, SILType loweredSubstArgType,
34303512 AbstractionPattern origParamType,
34313513 SILParameterInfo param) {
@@ -3806,6 +3888,66 @@ void DelayedArgument::emitBorrowedLValue(SILGenFunction &SGF,
38063888 // That should drain all the parameters.
38073889 assert (params.empty ());
38083890}
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+
38093951} // end anonymous namespace
38103952
38113953namespace {
0 commit comments