@@ -654,17 +654,24 @@ static void emitApplyArgument(IRGenFunction &IGF,
654
654
silConv.getSILType (substParam, substFnTy), in, out);
655
655
}
656
656
657
- static CanType getArgumentLoweringType (CanType type,
658
- SILParameterInfo paramInfo ) {
657
+ static CanType getArgumentLoweringType (CanType type, SILParameterInfo paramInfo,
658
+ bool isNoEscape ) {
659
659
switch (paramInfo.getConvention ()) {
660
660
// Capture value parameters by value, consuming them.
661
661
case ParameterConvention::Direct_Owned:
662
662
case ParameterConvention::Direct_Unowned:
663
663
case ParameterConvention::Direct_Guaranteed:
664
+ return type;
665
+ // Capture indirect parameters if the closure is not [onstack]. [onstack]
666
+ // closures don't take ownership of their arguments so we just capture the
667
+ // address.
664
668
case ParameterConvention::Indirect_In:
665
669
case ParameterConvention::Indirect_In_Constant:
666
670
case ParameterConvention::Indirect_In_Guaranteed:
667
- return type;
671
+ if (isNoEscape)
672
+ return CanInOutType::get (type);
673
+ else
674
+ return type;
668
675
669
676
// Capture inout parameters by pointer.
670
677
case ParameterConvention::Indirect_Inout:
@@ -1067,33 +1074,57 @@ static llvm::Function *emitPartialApplicationForwarder(IRGenModule &IGM,
1067
1074
auto fieldConvention = conventions[nextCapturedField];
1068
1075
Address fieldAddr = fieldLayout.project (subIGF, data, offsets);
1069
1076
auto &fieldTI = fieldLayout.getType ();
1070
- auto fieldSchema = fieldTI.getSchema ();
1071
1077
lastCapturedFieldPtr = fieldAddr.getAddress ();
1072
1078
1073
1079
Explosion param;
1074
1080
switch (fieldConvention) {
1075
1081
case ParameterConvention::Indirect_In:
1076
1082
case ParameterConvention::Indirect_In_Constant: {
1077
- // The +1 argument is passed indirectly, so we need to copy into a
1078
- // temporary.
1079
- needsAllocas = true ;
1080
- auto stackAddr = fieldTI.allocateStack (subIGF, fieldTy, " arg.temp" );
1081
- auto addressPointer = stackAddr.getAddress ().getAddress ();
1082
- fieldTI.initializeWithCopy (subIGF, stackAddr.getAddress (), fieldAddr,
1083
- fieldTy, false );
1084
- param.add (addressPointer);
1085
-
1086
- // Remember to deallocate later.
1087
- addressesToDeallocate.push_back (
1088
- AddressToDeallocate{fieldTy, fieldTI, stackAddr});
1089
1083
1084
+ auto initStackCopy = [&addressesToDeallocate, &needsAllocas, ¶m,
1085
+ &subIGF](const TypeInfo &fieldTI, SILType fieldTy,
1086
+ Address fieldAddr) {
1087
+ // The +1 argument is passed indirectly, so we need to copy into a
1088
+ // temporary.
1089
+ needsAllocas = true ;
1090
+ auto stackAddr = fieldTI.allocateStack (subIGF, fieldTy, " arg.temp" );
1091
+ auto addressPointer = stackAddr.getAddress ().getAddress ();
1092
+ fieldTI.initializeWithCopy (subIGF, stackAddr.getAddress (), fieldAddr,
1093
+ fieldTy, false );
1094
+ param.add (addressPointer);
1095
+
1096
+ // Remember to deallocate later.
1097
+ addressesToDeallocate.push_back (
1098
+ AddressToDeallocate{fieldTy, fieldTI, stackAddr});
1099
+ };
1100
+
1101
+ if (outType->isNoEscape ()) {
1102
+ // If the closure is [onstack] it only captured the address of the
1103
+ // value. Load that address from the context.
1104
+ Explosion addressExplosion;
1105
+ cast<LoadableTypeInfo>(fieldTI).loadAsCopy (subIGF, fieldAddr,
1106
+ addressExplosion);
1107
+ assert (fieldTy.isAddress ());
1108
+ auto newFieldTy = fieldTy.getObjectType ();
1109
+ auto &newFieldTI =
1110
+ subIGF.getTypeInfoForLowered (newFieldTy.getASTType ());
1111
+ fieldAddr =
1112
+ newFieldTI.getAddressForPointer (addressExplosion.claimNext ());
1113
+ initStackCopy (newFieldTI, newFieldTy, fieldAddr);
1114
+ } else {
1115
+ initStackCopy (fieldTI, fieldTy, fieldAddr);
1116
+ }
1090
1117
break ;
1091
1118
}
1092
1119
case ParameterConvention::Indirect_In_Guaranteed:
1093
- // The argument is +0, so we can use the address of the param in
1094
- // the context directly.
1095
- param.add (fieldAddr.getAddress ());
1096
- dependsOnContextLifetime = true ;
1120
+ if (outType->isNoEscape ()) {
1121
+ cast<LoadableTypeInfo>(fieldTI).loadAsCopy (subIGF, fieldAddr, param);
1122
+ } else {
1123
+ // The argument is +0, so we can use the address of the param in
1124
+ // the context directly.
1125
+ param.add (fieldAddr.getAddress ());
1126
+ dependsOnContextLifetime = true ;
1127
+ }
1097
1128
break ;
1098
1129
case ParameterConvention::Indirect_Inout:
1099
1130
case ParameterConvention::Indirect_InoutAliasable:
@@ -1343,7 +1374,8 @@ Optional<StackAddress> irgen::emitFunctionPartialApplication(
1343
1374
bool considerParameterSources = true ;
1344
1375
for (auto param : params) {
1345
1376
SILType argType = IGF.IGM .silConv .getSILType (param, origType);
1346
- auto argLoweringTy = getArgumentLoweringType (argType.getASTType (), param);
1377
+ auto argLoweringTy = getArgumentLoweringType (argType.getASTType (), param,
1378
+ outType->isNoEscape ());
1347
1379
auto &ti = IGF.getTypeInfoForLowered (argLoweringTy);
1348
1380
1349
1381
if (!isa<FixedTypeInfo>(ti)) {
@@ -1370,7 +1402,8 @@ Optional<StackAddress> irgen::emitFunctionPartialApplication(
1370
1402
for (auto param : params) {
1371
1403
SILType argType = IGF.IGM .silConv .getSILType (param, origType);
1372
1404
1373
- auto argLoweringTy = getArgumentLoweringType (argType.getASTType (), param);
1405
+ auto argLoweringTy = getArgumentLoweringType (argType.getASTType (), param,
1406
+ outType->isNoEscape ());
1374
1407
1375
1408
auto &ti = IGF.getTypeInfoForLowered (argLoweringTy);
1376
1409
@@ -1608,9 +1641,15 @@ Optional<StackAddress> irgen::emitFunctionPartialApplication(
1608
1641
case ParameterConvention::Indirect_In:
1609
1642
case ParameterConvention::Indirect_In_Constant:
1610
1643
case ParameterConvention::Indirect_In_Guaranteed: {
1611
- auto addr = fieldLayout.getType ().getAddressForPointer (args.claimNext ());
1612
- fieldLayout.getType ().initializeWithTake (IGF, fieldAddr, addr, fieldTy,
1613
- isOutlined);
1644
+ if (outType->isNoEscape ()) {
1645
+ cast<LoadableTypeInfo>(fieldLayout.getType ())
1646
+ .initialize (IGF, args, fieldAddr, isOutlined);
1647
+ } else {
1648
+ auto addr =
1649
+ fieldLayout.getType ().getAddressForPointer (args.claimNext ());
1650
+ fieldLayout.getType ().initializeWithTake (IGF, fieldAddr, addr,
1651
+ fieldTy, isOutlined);
1652
+ }
1614
1653
break ;
1615
1654
}
1616
1655
// Take direct value arguments and inout pointers by value.
0 commit comments