@@ -229,179 +229,6 @@ static SILValue implodeTupleValues(ArrayRef<ManagedValue> values,
229
229
return ImplodeLoadableTupleValue<KIND>(values, gen).visit (tupleType, l);
230
230
}
231
231
232
- class CopyIntoTupleValues
233
- : public CanTypeVisitor<CopyIntoTupleValues,
234
- /* RetTy=*/ void ,
235
- /* Args...=*/ Initialization*>
236
- {
237
- public:
238
- ArrayRef<ManagedValue> values;
239
- SILGenFunction &gen;
240
- SILLocation loc;
241
-
242
- CopyIntoTupleValues (ArrayRef<ManagedValue> values, SILGenFunction &gen,
243
- SILLocation l)
244
- : values(values), gen(gen), loc(l)
245
- {}
246
-
247
- void visitType (CanType t, Initialization *I) {
248
- // Pop a value off.
249
- ManagedValue orig = values[0 ];
250
- values = values.slice (1 );
251
-
252
- switch (I->kind ) {
253
- case Initialization::Kind::Tuple:
254
- llvm_unreachable (" tuple initialization not destructured?!" );
255
-
256
- case Initialization::Kind::Ignored:
257
- // Throw out the value without copying it.
258
- return ;
259
-
260
- case Initialization::Kind::Translating: {
261
- auto copy = orig.copyUnmanaged (gen, loc);
262
- I->translateValue (gen, loc, copy);
263
- I->finishInitialization (gen);
264
- return ;
265
- }
266
-
267
- case Initialization::Kind::LetValue:
268
- // If this is a non-address-only let, just bind the value.
269
- if (!I->hasAddress ()) {
270
- // Disable the expression cleanup of the copy, since the let value
271
- // initialization has a cleanup that lives for the entire scope of the
272
- // let declaration.
273
- I->bindValue (orig.copyUnmanaged (gen, loc).forward (gen), gen);
274
- I->finishInitialization (gen);
275
- return ;
276
- }
277
- // Otherwise, handle it the same as the singlebuffer case.
278
- SWIFT_FALLTHROUGH;
279
-
280
- case Initialization::Kind::SingleBuffer:
281
- assert (orig.getValue () != I->getAddress () && " copying in place?!" );
282
- orig.copyInto (gen, I->getAddress (), loc);
283
- I->finishInitialization (gen);
284
- return ;
285
- }
286
- }
287
-
288
- void visitTupleType (CanTupleType t, Initialization *I) {
289
- // Break up the aggregate initialization if we can.
290
- if (I->canSplitIntoSubelementAddresses ()) {
291
- SmallVector<InitializationPtr, 4 > subInitBuf;
292
- auto subInits = I->getSubInitializationsForTuple (gen, t, subInitBuf, loc);
293
-
294
- assert (subInits.size () == t->getNumElements () &&
295
- " initialization does not match tuple?!" );
296
-
297
- for (unsigned i = 0 , e = subInits.size (); i < e; ++i)
298
- visit (t.getElementType (i), subInits[i].get ());
299
- return ;
300
- }
301
-
302
- // Otherwise, process this by turning the values corresponding to the tuple
303
- // into a single value (through an implosion) and then binding that value to
304
- // our initialization.
305
- assert (I->kind == Initialization::Kind::LetValue);
306
- SILValue V = implodeTupleValues<ImplodeKind::Copy>(values, gen, t, loc);
307
-
308
- // This will have just used up the first values in the list, pop them off.
309
- values = values.slice (getRValueSize (t));
310
-
311
- I->bindValue (V, gen);
312
- I->finishInitialization (gen);
313
- }
314
- };
315
-
316
- class InitializeTupleValues
317
- : public CanTypeVisitor<InitializeTupleValues,
318
- /* RetTy=*/ void ,
319
- /* Args...=*/ Initialization*>
320
- {
321
- public:
322
- ArrayRef<ManagedValue> values;
323
- SILGenFunction &gen;
324
- SILLocation loc;
325
-
326
- InitializeTupleValues (ArrayRef<ManagedValue> values, SILGenFunction &gen,
327
- SILLocation l)
328
- : values(values), gen(gen), loc(l)
329
- {}
330
-
331
- void visitType (CanType t, Initialization *I) {
332
- // Pop a result off.
333
- ManagedValue result = values[0 ];
334
- values = values.slice (1 );
335
-
336
- switch (I->kind ) {
337
- case Initialization::Kind::Tuple:
338
- llvm_unreachable (" tuple initialization not destructured?!" );
339
-
340
- case Initialization::Kind::Ignored:
341
- // Throw out the value without storing it.
342
- return ;
343
-
344
- case Initialization::Kind::Translating:
345
- I->translateValue (gen, loc, result);
346
- I->finishInitialization (gen);
347
- return ;
348
-
349
- case Initialization::Kind::LetValue:
350
- // If this is a non-address-only let, just bind the value.
351
- if (!I->hasAddress ()) {
352
- // Disable the rvalue expression cleanup, since the let value
353
- // initialization has a cleanup that lives for the entire scope of the
354
- // let declaration.
355
- I->bindValue (result.forward (gen), gen);
356
- I->finishInitialization (gen);
357
- return ;
358
- }
359
- // Otherwise, handle it the same as the singlebuffer case.
360
- SWIFT_FALLTHROUGH;
361
-
362
- case Initialization::Kind::SingleBuffer:
363
- // If we didn't evaluate into the initialization buffer, do so now.
364
- if (result.getValue () != I->getAddress ()) {
365
- result.forwardInto (gen, loc, I->getAddress ());
366
- } else {
367
- // If we did evaluate into the initialization buffer, disable the
368
- // cleanup.
369
- result.forwardCleanup (gen);
370
- }
371
-
372
- I->finishInitialization (gen);
373
- return ;
374
- }
375
- }
376
-
377
- void visitTupleType (CanTupleType t, Initialization *I) {
378
- // Break up the aggregate initialization if we can.
379
- if (I->canSplitIntoSubelementAddresses ()) {
380
- SmallVector<InitializationPtr, 4 > subInitBuf;
381
- auto subInits = I->getSubInitializationsForTuple (gen, t, subInitBuf, loc);
382
-
383
- assert (subInits.size () == t->getNumElements () &&
384
- " initialization does not match tuple?!" );
385
-
386
- for (unsigned i = 0 , e = subInits.size (); i < e; ++i)
387
- visit (t.getElementType (i), subInits[i].get ());
388
- return ;
389
- }
390
-
391
- // Otherwise, process this by turning the values corresponding to the tuple
392
- // into a single value (through an implosion) and then binding that value to
393
- // our initialization.
394
- assert (I->kind == Initialization::Kind::LetValue);
395
- SILValue V = implodeTupleValues<ImplodeKind::Forward>(values, gen, t, loc);
396
-
397
- // This will have just used up the first values in the list, pop them off.
398
- values = values.slice (getRValueSize (t));
399
-
400
- I->bindValue (V, gen);
401
- I->finishInitialization (gen);
402
- }
403
- };
404
-
405
232
class EmitBBArguments : public CanTypeVisitor <EmitBBArguments,
406
233
/* RetTy*/ RValue>
407
234
{
@@ -451,6 +278,73 @@ class EmitBBArguments : public CanTypeVisitor<EmitBBArguments,
451
278
452
279
} // end anonymous namespace
453
280
281
+
282
+ // / Perform a copy or init operation from an array of ManagedValue (from an
283
+ // / RValue) into an initialization. The RValue will have one scalar ManagedValue
284
+ // / for each exploded tuple element in the RValue, so this needs to make the
285
+ // / shape of the initialization match the available elements. This can be done
286
+ // / one one of two ways:
287
+ // /
288
+ // / 1) recursively scalarize down the initialization on demand if the type of
289
+ // / the RValue is tuple type and the initialization supports it.
290
+ // / 2) implode the corresponding values in the RValue to a scalar value of
291
+ // / tuple type and process them as a unit.
292
+ // /
293
+ // / We prefer to use approach #1 since it generates better code.
294
+ // /
295
+ template <ImplodeKind KIND>
296
+ static void copyOrInitValuesInto (Initialization *init,
297
+ ArrayRef<ManagedValue> &values, CanType type,
298
+ SILLocation loc, SILGenFunction &gen) {
299
+ bool isInit;
300
+ switch (KIND) {
301
+ case ImplodeKind::Unmanaged: assert (0 && " Not handled by init" );
302
+ case ImplodeKind::Forward: isInit = true ; break ;
303
+ case ImplodeKind::Copy: isInit = false ; break ;
304
+ }
305
+
306
+ // If the element has non-tuple type, just serve it up to the initialization.
307
+ auto tupleType = dyn_cast<TupleType>(type);
308
+ if (!tupleType) {
309
+ // We take the first value.
310
+ ManagedValue result = values[0 ];
311
+ values = values.slice (1 );
312
+ init->copyOrInitValueInto (result, isInit, loc, gen);
313
+ init->finishInitialization (gen);
314
+ return ;
315
+ }
316
+
317
+
318
+ // If we can satisfy the tuple type by breaking up the aggregate
319
+ // initialization, do so.
320
+ if (init->canSplitIntoSubelementAddresses ()) {
321
+ SmallVector<InitializationPtr, 4 > subInitBuf;
322
+ auto subInits = init->getSubInitializationsForTuple (gen, type,
323
+ subInitBuf, loc);
324
+
325
+ assert (subInits.size () == tupleType->getNumElements () &&
326
+ " initialization does not match tuple?!" );
327
+
328
+ for (unsigned i = 0 , e = subInits.size (); i < e; ++i)
329
+ copyOrInitValuesInto<KIND>(subInits[i].get (), values,
330
+ tupleType.getElementType (i), loc, gen);
331
+ return ;
332
+ }
333
+
334
+ // Otherwise, process this by turning the values corresponding to the tuple
335
+ // into a single value (through an implosion) and then binding that value to
336
+ // our initialization.
337
+ SILValue scalar = implodeTupleValues<KIND>(values, gen, type, loc);
338
+
339
+ // This will have just used up the first values in the list, pop them off.
340
+ values = values.slice (getRValueSize (type));
341
+
342
+ init->copyOrInitValueInto (ManagedValue::forUnmanaged (scalar), isInit, loc,
343
+ gen);
344
+ init->finishInitialization (gen);
345
+ }
346
+
347
+
454
348
RValue::RValue (ArrayRef<ManagedValue> values, CanType type)
455
349
: values(values.begin(), values.end()), type(type), elementsToBeAdded(0 ) {
456
350
if (values.size () == 1 && values[0 ].isInContext ()) {
@@ -540,14 +434,16 @@ SILValue RValue::forwardAsSingleStorageValue(SILGenFunction &gen,
540
434
void RValue::forwardInto (SILGenFunction &gen, Initialization *I,
541
435
SILLocation loc) && {
542
436
assert (isComplete () && " rvalue is not complete" );
543
- InitializeTupleValues (values, gen, loc).visit (type, I);
437
+
438
+ ArrayRef<ManagedValue> elts = values;
439
+ copyOrInitValuesInto<ImplodeKind::Forward>(I, elts, type, loc, gen);
544
440
}
545
441
546
442
void RValue::copyInto (SILGenFunction &gen, Initialization *I,
547
443
SILLocation loc) const & {
548
444
assert (isComplete () && " rvalue is not complete" );
549
-
550
- CopyIntoTupleValues (values, gen, loc). visit ( type, I );
445
+ ArrayRef<ManagedValue> elts = values;
446
+ copyOrInitValuesInto<ImplodeKind::Copy>(I, elts, type, loc, gen );
551
447
}
552
448
553
449
ManagedValue RValue::getAsSingleValue (SILGenFunction &gen, SILLocation l) && {
0 commit comments