@@ -27,6 +27,15 @@ using namespace Lowering;
27
27
// Result Plans
28
28
// ===----------------------------------------------------------------------===//
29
29
30
+ void ResultPlan::finishAndAddTo (SILGenFunction &SGF, SILLocation loc,
31
+ ArrayRef<ManagedValue> &directResults,
32
+ SILValue bridgedForeignError,
33
+ RValue &result) {
34
+ auto rvalue = finish (SGF, loc, directResults, bridgedForeignError);
35
+ assert (!rvalue.isInContext ());
36
+ result.addElement (std::move (rvalue));
37
+ }
38
+
30
39
namespace {
31
40
32
41
// / A result plan for evaluating an indirect result into the address
@@ -343,14 +352,16 @@ class ScalarResultPlan final : public ResultPlan {
343
352
// / using a temporary buffer initialized by a sub-plan.
344
353
class InitValueFromTemporaryResultPlan final : public ResultPlan {
345
354
Initialization *init;
355
+ CanType substType;
346
356
ResultPlanPtr subPlan;
347
357
std::unique_ptr<TemporaryInitialization> temporary;
348
358
349
359
public:
350
360
InitValueFromTemporaryResultPlan (
351
- Initialization *init, ResultPlanPtr &&subPlan,
361
+ Initialization *init, CanType substType,
362
+ ResultPlanPtr &&subPlan,
352
363
std::unique_ptr<TemporaryInitialization> &&temporary)
353
- : init(init), subPlan(std::move(subPlan)),
364
+ : init(init), substType(substType), subPlan(std::move(subPlan)),
354
365
temporary (std::move(temporary)) {}
355
366
356
367
RValue finish (SILGenFunction &SGF, SILLocation loc,
@@ -362,10 +373,15 @@ class InitValueFromTemporaryResultPlan final : public ResultPlan {
362
373
(void )subResult;
363
374
364
375
ManagedValue value = temporary->getManagedAddress ();
365
- init->copyOrInitValueInto (SGF, loc, value, /* init*/ true );
366
- init->finishInitialization (SGF);
367
376
368
- return RValue::forInContext ();
377
+ if (init) {
378
+ init->copyOrInitValueInto (SGF, loc, value, /* init*/ true );
379
+ init->finishInitialization (SGF);
380
+
381
+ return RValue::forInContext ();
382
+ }
383
+
384
+ return RValue (SGF, loc, substType, value);
369
385
}
370
386
371
387
void
@@ -414,28 +430,30 @@ class PackExpansionResultPlan : public ResultPlan {
414
430
public:
415
431
PackExpansionResultPlan (ResultPlanBuilder &builder,
416
432
SILValue packAddr,
417
- MutableArrayRef<InitializationPtr> inits,
433
+ Optional< MutableArrayRef<InitializationPtr> > inits,
418
434
AbstractionPattern origExpansionType,
419
435
CanTupleEltTypeArrayRef substEltTypes)
420
436
: PackAddr(packAddr) {
437
+ assert (!inits || inits->size () == substEltTypes.size ());
438
+
421
439
auto packTy = packAddr->getType ().castTo <SILPackType>();
422
440
auto formalPackType =
423
441
CanPackType::get (packTy->getASTContext (), substEltTypes);
424
442
auto origPatternType = origExpansionType.getPackExpansionPatternType ();
425
443
426
- ComponentPlans.reserve (inits .size ());
427
- for (auto i : indices (inits )) {
428
- auto & init = inits[i];
444
+ ComponentPlans.reserve (substEltTypes .size ());
445
+ for (auto i : indices (substEltTypes )) {
446
+ Initialization * init = inits ? (*inits) [i]. get () : nullptr ;
429
447
CanType substEltType = substEltTypes[i];
430
448
431
449
if (isa<PackExpansionType>(substEltType)) {
432
450
ComponentPlans.emplace_back (
433
451
builder.buildPackExpansionIntoPack (packAddr, formalPackType, i,
434
- init. get () , origPatternType));
452
+ init, origPatternType));
435
453
} else {
436
454
ComponentPlans.emplace_back (
437
455
builder.buildScalarIntoPack (packAddr, formalPackType, i,
438
- init. get () , origPatternType));
456
+ init, origPatternType));
439
457
}
440
458
}
441
459
}
@@ -451,6 +469,16 @@ class PackExpansionResultPlan : public ResultPlan {
451
469
return RValue::forInContext ();
452
470
}
453
471
472
+ void finishAndAddTo (SILGenFunction &SGF, SILLocation loc,
473
+ ArrayRef<ManagedValue> &directResults,
474
+ SILValue bridgedForeignError,
475
+ RValue &result) override {
476
+ for (auto &componentPlan : ComponentPlans) {
477
+ componentPlan->finishAndAddTo (SGF, loc, directResults,
478
+ bridgedForeignError, result);
479
+ }
480
+ }
481
+
454
482
void gatherIndirectResultAddrs (SILGenFunction &SGF, SILLocation loc,
455
483
SmallVectorImpl<SILValue> &outList) const override {
456
484
outList.push_back (PackAddr);
@@ -557,19 +585,27 @@ class PackTransformResultPlan final : public ResultPlan {
557
585
// / components.
558
586
class TupleRValueResultPlan final : public ResultPlan {
559
587
CanTupleType substType;
560
- SmallVector<ResultPlanPtr, 4 > eltPlans;
588
+
589
+ SmallVector<ResultPlanPtr, 4 > origEltPlans;
561
590
562
591
public:
563
592
TupleRValueResultPlan (ResultPlanBuilder &builder, AbstractionPattern origType,
564
593
CanTupleType substType)
565
594
: substType(substType) {
566
595
// Create plans for all the elements.
567
- eltPlans.reserve (substType->getNumElements ());
568
- for (auto i : indices (substType->getElementTypes ())) {
569
- AbstractionPattern origEltType = origType.getTupleElementType (i);
570
- CanType substEltType = substType.getElementType (i);
571
- eltPlans.push_back (builder.build (nullptr , origEltType, substEltType));
572
- }
596
+ origEltPlans.reserve (substType->getNumElements ());
597
+ origType.forEachTupleElement (substType,
598
+ [&](TupleElementGenerator &origElt) {
599
+ AbstractionPattern origEltType = origElt.getOrigType ();
600
+ auto substEltTypes = origElt.getSubstTypes ();
601
+ if (!origElt.isOrigPackExpansion ()) {
602
+ origEltPlans.push_back (
603
+ builder.build (nullptr , origEltType, substEltTypes[0 ]));
604
+ } else {
605
+ origEltPlans.push_back (
606
+ builder.buildForPackExpansion (None, origEltType, substEltTypes));
607
+ }
608
+ });
573
609
}
574
610
575
611
RValue finish (SILGenFunction &SGF, SILLocation loc,
@@ -578,10 +614,9 @@ class TupleRValueResultPlan final : public ResultPlan {
578
614
RValue tupleRV (substType);
579
615
580
616
// Finish all the component tuples.
581
- for (auto &plan : eltPlans) {
582
- RValue eltRV =
583
- plan->finish (SGF, loc, directResults, bridgedForeignError);
584
- tupleRV.addElement (std::move (eltRV));
617
+ for (auto &plan : origEltPlans) {
618
+ plan->finishAndAddTo (SGF, loc, directResults, bridgedForeignError,
619
+ tupleRV);
585
620
}
586
621
587
622
return tupleRV;
@@ -590,8 +625,8 @@ class TupleRValueResultPlan final : public ResultPlan {
590
625
void
591
626
gatherIndirectResultAddrs (SILGenFunction &SGF, SILLocation loc,
592
627
SmallVectorImpl<SILValue> &outList) const override {
593
- for (const auto &eltPlan : eltPlans ) {
594
- eltPlan ->gatherIndirectResultAddrs (SGF, loc, outList);
628
+ for (const auto &plan : origEltPlans ) {
629
+ plan ->gatherIndirectResultAddrs (SGF, loc, outList);
595
630
}
596
631
}
597
632
};
@@ -1143,10 +1178,10 @@ ResultPlanPtr ResultPlanBuilder::buildForScalar(Initialization *init,
1143
1178
}
1144
1179
1145
1180
ResultPlanPtr ResultPlanBuilder::
1146
- buildForPackExpansion (MutableArrayRef<InitializationPtr> inits,
1181
+ buildForPackExpansion (Optional< MutableArrayRef<InitializationPtr> > inits,
1147
1182
AbstractionPattern origExpansionType,
1148
1183
CanTupleEltTypeArrayRef substTypes) {
1149
- assert (inits. size () == substTypes.size ());
1184
+ assert (! inits || inits-> size () == substTypes.size ());
1150
1185
1151
1186
// Pack expansions in the original result type always turn into
1152
1187
// a single @pack_out result.
@@ -1155,7 +1190,7 @@ ResultPlanPtr ResultPlanBuilder::
1155
1190
auto packTy =
1156
1191
result.getSILStorageType (SGF.SGM .M , calleeTypeInfo.substFnType ,
1157
1192
SGF.getTypeExpansionContext ());
1158
- assert (packTy.castTo <SILPackType>()->getNumElements () == inits .size ());
1193
+ assert (packTy.castTo <SILPackType>()->getNumElements () == substTypes .size ());
1159
1194
1160
1195
// TODO: try to just forward a single pack
1161
1196
@@ -1236,7 +1271,6 @@ ResultPlanBuilder::buildScalarIntoPack(SILValue packAddr,
1236
1271
Initialization *init,
1237
1272
AbstractionPattern origType) {
1238
1273
assert (!origType.isPackExpansion ());
1239
- assert (init);
1240
1274
auto substType = formalPackType.getElementType (componentIndex);
1241
1275
assert (!isa<PackExpansionType>(substType));
1242
1276
@@ -1245,7 +1279,8 @@ ResultPlanBuilder::buildScalarIntoPack(SILValue packAddr,
1245
1279
->getElementType (componentIndex);
1246
1280
SILResultInfo resultInfo (loweredEltType, ResultConvention::Indirect);
1247
1281
1248
- // Use the normal scalar emission path.
1282
+ // Use the normal scalar emission path to gather an indirect result
1283
+ // of that type.
1249
1284
auto plan = buildForScalar (init, origType, substType, resultInfo);
1250
1285
1251
1286
// Immediately gather the indirect result.
@@ -1265,38 +1300,44 @@ ResultPlanBuilder::buildScalarIntoPack(SILValue packAddr,
1265
1300
ResultPlanPtr ResultPlanBuilder::buildForTuple (Initialization *init,
1266
1301
AbstractionPattern origType,
1267
1302
CanTupleType substType) {
1268
- // If we don't have an initialization for the tuple, just build the
1269
- // individual components.
1270
- if (!init) {
1271
- return ResultPlanPtr (new TupleRValueResultPlan (*this , origType, substType));
1272
- }
1273
-
1274
- // Okay, we have an initialization for the tuple that we need to emit into.
1275
-
1276
- // If we can just split the initialization, do so.
1277
- if (init->canSplitIntoTupleElements ()) {
1303
+ // If we have an initialization, and we can split it, do so.
1304
+ if (init && init->canSplitIntoTupleElements ()) {
1278
1305
return ResultPlanPtr (
1279
1306
new TupleInitializationResultPlan (*this , init, origType, substType));
1280
1307
}
1281
1308
1282
- // Otherwise, we're going to have to call copyOrInitValueInto, which only
1283
- // takes a single value.
1284
-
1285
- // If the tuple is address-only, we'll get much better code if we
1286
- // emit into a single buffer.
1309
+ // Otherwise, if the tuple contains a pack expansion, we'll need to
1310
+ // initialize a single buffer one way or another: either we're giving
1311
+ // this to RValue (which wants a single value for tuples with pack
1312
+ // expansions) or we'll have to call copyOrInitValueInto on init
1313
+ // (which expects a single value). Create a temporary, build into
1314
+ // that, and then call the initialization.
1315
+ //
1316
+ // We also use this path when we have an init and the type is
1317
+ // address-only, because we'll need to call copyOrInitValueInto and
1318
+ // we'll get better code by building that up indirectly. But we don't
1319
+ // do that if we're not using lowered addresses because we prefer to
1320
+ // build tuples with scalar operations.
1287
1321
auto &substTL = SGF.getTypeLowering (substType);
1322
+ assert (substTL.isAddressOnly () || !substType.containsPackExpansionType ());
1288
1323
if (substTL.isAddressOnly () &&
1289
1324
(substType.containsPackExpansionType () ||
1290
- SGF.F .getConventions ().useLoweredAddresses ())) {
1325
+ (init != nullptr && SGF.F .getConventions ().useLoweredAddresses () ))) {
1291
1326
// Create a temporary.
1292
1327
auto temporary = SGF.emitTemporary (loc, substTL);
1293
1328
1294
1329
// Build a sub-plan to emit into the temporary.
1295
1330
auto subplan = buildForTuple (temporary.get (), origType, substType);
1296
1331
1297
- // Make a plan to initialize into that.
1332
+ // Make a plan to produce the final result from that.
1298
1333
return ResultPlanPtr (new InitValueFromTemporaryResultPlan (
1299
- init, std::move (subplan), std::move (temporary)));
1334
+ init, substType, std::move (subplan), std::move (temporary)));
1335
+ }
1336
+
1337
+ // If we don't have an initialization, just build the individual
1338
+ // components.
1339
+ if (!init) {
1340
+ return ResultPlanPtr (new TupleRValueResultPlan (*this , origType, substType));
1300
1341
}
1301
1342
1302
1343
// Build a sub-plan that doesn't know about the initialization.
0 commit comments