@@ -27,6 +27,15 @@ using namespace Lowering;
2727// Result Plans
2828// ===----------------------------------------------------------------------===//
2929
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+
3039namespace {
3140
3241// / A result plan for evaluating an indirect result into the address
@@ -343,14 +352,16 @@ class ScalarResultPlan final : public ResultPlan {
343352// / using a temporary buffer initialized by a sub-plan.
344353class InitValueFromTemporaryResultPlan final : public ResultPlan {
345354 Initialization *init;
355+ CanType substType;
346356 ResultPlanPtr subPlan;
347357 std::unique_ptr<TemporaryInitialization> temporary;
348358
349359public:
350360 InitValueFromTemporaryResultPlan (
351- Initialization *init, ResultPlanPtr &&subPlan,
361+ Initialization *init, CanType substType,
362+ ResultPlanPtr &&subPlan,
352363 std::unique_ptr<TemporaryInitialization> &&temporary)
353- : init(init), subPlan(std::move(subPlan)),
364+ : init(init), substType(substType), subPlan(std::move(subPlan)),
354365 temporary (std::move(temporary)) {}
355366
356367 RValue finish (SILGenFunction &SGF, SILLocation loc,
@@ -362,10 +373,15 @@ class InitValueFromTemporaryResultPlan final : public ResultPlan {
362373 (void )subResult;
363374
364375 ManagedValue value = temporary->getManagedAddress ();
365- init->copyOrInitValueInto (SGF, loc, value, /* init*/ true );
366- init->finishInitialization (SGF);
367376
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);
369385 }
370386
371387 void
@@ -414,28 +430,30 @@ class PackExpansionResultPlan : public ResultPlan {
414430public:
415431 PackExpansionResultPlan (ResultPlanBuilder &builder,
416432 SILValue packAddr,
417- MutableArrayRef<InitializationPtr> inits,
433+ Optional< MutableArrayRef<InitializationPtr> > inits,
418434 AbstractionPattern origExpansionType,
419435 CanTupleEltTypeArrayRef substEltTypes)
420436 : PackAddr(packAddr) {
437+ assert (!inits || inits->size () == substEltTypes.size ());
438+
421439 auto packTy = packAddr->getType ().castTo <SILPackType>();
422440 auto formalPackType =
423441 CanPackType::get (packTy->getASTContext (), substEltTypes);
424442 auto origPatternType = origExpansionType.getPackExpansionPatternType ();
425443
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 ;
429447 CanType substEltType = substEltTypes[i];
430448
431449 if (isa<PackExpansionType>(substEltType)) {
432450 ComponentPlans.emplace_back (
433451 builder.buildPackExpansionIntoPack (packAddr, formalPackType, i,
434- init. get () , origPatternType));
452+ init, origPatternType));
435453 } else {
436454 ComponentPlans.emplace_back (
437455 builder.buildScalarIntoPack (packAddr, formalPackType, i,
438- init. get () , origPatternType));
456+ init, origPatternType));
439457 }
440458 }
441459 }
@@ -451,6 +469,16 @@ class PackExpansionResultPlan : public ResultPlan {
451469 return RValue::forInContext ();
452470 }
453471
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+
454482 void gatherIndirectResultAddrs (SILGenFunction &SGF, SILLocation loc,
455483 SmallVectorImpl<SILValue> &outList) const override {
456484 outList.push_back (PackAddr);
@@ -557,19 +585,27 @@ class PackTransformResultPlan final : public ResultPlan {
557585// / components.
558586class TupleRValueResultPlan final : public ResultPlan {
559587 CanTupleType substType;
560- SmallVector<ResultPlanPtr, 4 > eltPlans;
588+
589+ SmallVector<ResultPlanPtr, 4 > origEltPlans;
561590
562591public:
563592 TupleRValueResultPlan (ResultPlanBuilder &builder, AbstractionPattern origType,
564593 CanTupleType substType)
565594 : substType(substType) {
566595 // 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+ });
573609 }
574610
575611 RValue finish (SILGenFunction &SGF, SILLocation loc,
@@ -578,10 +614,9 @@ class TupleRValueResultPlan final : public ResultPlan {
578614 RValue tupleRV (substType);
579615
580616 // 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);
585620 }
586621
587622 return tupleRV;
@@ -590,8 +625,8 @@ class TupleRValueResultPlan final : public ResultPlan {
590625 void
591626 gatherIndirectResultAddrs (SILGenFunction &SGF, SILLocation loc,
592627 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);
595630 }
596631 }
597632};
@@ -1143,10 +1178,10 @@ ResultPlanPtr ResultPlanBuilder::buildForScalar(Initialization *init,
11431178}
11441179
11451180ResultPlanPtr ResultPlanBuilder::
1146- buildForPackExpansion (MutableArrayRef<InitializationPtr> inits,
1181+ buildForPackExpansion (Optional< MutableArrayRef<InitializationPtr> > inits,
11471182 AbstractionPattern origExpansionType,
11481183 CanTupleEltTypeArrayRef substTypes) {
1149- assert (inits. size () == substTypes.size ());
1184+ assert (! inits || inits-> size () == substTypes.size ());
11501185
11511186 // Pack expansions in the original result type always turn into
11521187 // a single @pack_out result.
@@ -1155,7 +1190,7 @@ ResultPlanPtr ResultPlanBuilder::
11551190 auto packTy =
11561191 result.getSILStorageType (SGF.SGM .M , calleeTypeInfo.substFnType ,
11571192 SGF.getTypeExpansionContext ());
1158- assert (packTy.castTo <SILPackType>()->getNumElements () == inits .size ());
1193+ assert (packTy.castTo <SILPackType>()->getNumElements () == substTypes .size ());
11591194
11601195 // TODO: try to just forward a single pack
11611196
@@ -1236,7 +1271,6 @@ ResultPlanBuilder::buildScalarIntoPack(SILValue packAddr,
12361271 Initialization *init,
12371272 AbstractionPattern origType) {
12381273 assert (!origType.isPackExpansion ());
1239- assert (init);
12401274 auto substType = formalPackType.getElementType (componentIndex);
12411275 assert (!isa<PackExpansionType>(substType));
12421276
@@ -1245,7 +1279,8 @@ ResultPlanBuilder::buildScalarIntoPack(SILValue packAddr,
12451279 ->getElementType (componentIndex);
12461280 SILResultInfo resultInfo (loweredEltType, ResultConvention::Indirect);
12471281
1248- // Use the normal scalar emission path.
1282+ // Use the normal scalar emission path to gather an indirect result
1283+ // of that type.
12491284 auto plan = buildForScalar (init, origType, substType, resultInfo);
12501285
12511286 // Immediately gather the indirect result.
@@ -1265,38 +1300,44 @@ ResultPlanBuilder::buildScalarIntoPack(SILValue packAddr,
12651300ResultPlanPtr ResultPlanBuilder::buildForTuple (Initialization *init,
12661301 AbstractionPattern origType,
12671302 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 ()) {
12781305 return ResultPlanPtr (
12791306 new TupleInitializationResultPlan (*this , init, origType, substType));
12801307 }
12811308
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.
12871321 auto &substTL = SGF.getTypeLowering (substType);
1322+ assert (substTL.isAddressOnly () || !substType.containsPackExpansionType ());
12881323 if (substTL.isAddressOnly () &&
12891324 (substType.containsPackExpansionType () ||
1290- SGF.F .getConventions ().useLoweredAddresses ())) {
1325+ (init != nullptr && SGF.F .getConventions ().useLoweredAddresses () ))) {
12911326 // Create a temporary.
12921327 auto temporary = SGF.emitTemporary (loc, substTL);
12931328
12941329 // Build a sub-plan to emit into the temporary.
12951330 auto subplan = buildForTuple (temporary.get (), origType, substType);
12961331
1297- // Make a plan to initialize into that.
1332+ // Make a plan to produce the final result from that.
12981333 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));
13001341 }
13011342
13021343 // Build a sub-plan that doesn't know about the initialization.
0 commit comments