@@ -315,57 +315,6 @@ void BorrowScopeIntroducingValue::visitLocalScopeEndingUses(
315
315
llvm_unreachable (" Covered switch isn't covered?!" );
316
316
}
317
317
318
- bool swift::getUnderlyingBorrowIntroducingValues (
319
- SILValue inputValue, SmallVectorImpl<BorrowScopeIntroducingValue> &out) {
320
- if (inputValue.getOwnershipKind () != ValueOwnershipKind::Guaranteed)
321
- return false ;
322
-
323
- SmallVector<SILValue, 32 > worklist;
324
- worklist.emplace_back (inputValue);
325
-
326
- while (!worklist.empty ()) {
327
- SILValue v = worklist.pop_back_val ();
328
-
329
- // First check if v is an introducer. If so, stash it and continue.
330
- if (auto scopeIntroducer = BorrowScopeIntroducingValue::get (v)) {
331
- out.push_back (*scopeIntroducer);
332
- continue ;
333
- }
334
-
335
- // If v produces .none ownership, then we can ignore it. It is important
336
- // that we put this before checking for guaranteed forwarding instructions,
337
- // since we want to ignore guaranteed forwarding instructions that in this
338
- // specific case produce a .none value.
339
- if (v.getOwnershipKind () == ValueOwnershipKind::None)
340
- continue ;
341
-
342
- // Otherwise if v is an ownership forwarding value, add its defining
343
- // instruction
344
- if (isGuaranteedForwardingValue (v)) {
345
- if (auto *i = v->getDefiningInstruction ()) {
346
- llvm::transform (i->getAllOperands (), std::back_inserter (worklist),
347
- [](const Operand &op) -> SILValue { return op.get (); });
348
- continue ;
349
- }
350
-
351
- // Otherwise, we should have a block argument that is defined by a single
352
- // predecessor terminator.
353
- auto *arg = cast<SILPhiArgument>(v);
354
- auto *termInst = arg->getSingleTerminator ();
355
- assert (termInst && termInst->isTransformationTerminator ());
356
- llvm::transform (termInst->getAllOperands (), std::back_inserter (worklist),
357
- [](const Operand &op) -> SILValue { return op.get (); });
358
- continue ;
359
- }
360
-
361
- // Otherwise, this is an introducer we do not understand. Bail and return
362
- // false.
363
- return false ;
364
- }
365
-
366
- return true ;
367
- }
368
-
369
318
llvm::raw_ostream &swift::operator <<(llvm::raw_ostream &os,
370
319
BorrowScopeIntroducingValueKind kind) {
371
320
kind.print (os);
@@ -448,3 +397,107 @@ bool BorrowScopeIntroducingValue::visitLocalScopeTransitiveEndingUses(
448
397
449
398
return foundError;
450
399
}
400
+
401
+ // ===----------------------------------------------------------------------===//
402
+ // Introducer Searching Routines
403
+ // ===----------------------------------------------------------------------===//
404
+
405
+ bool swift::getAllBorrowIntroducingValues (
406
+ SILValue inputValue, SmallVectorImpl<BorrowScopeIntroducingValue> &out) {
407
+ if (inputValue.getOwnershipKind () != ValueOwnershipKind::Guaranteed)
408
+ return false ;
409
+
410
+ SmallVector<SILValue, 32 > worklist;
411
+ worklist.emplace_back (inputValue);
412
+
413
+ while (!worklist.empty ()) {
414
+ SILValue value = worklist.pop_back_val ();
415
+
416
+ // First check if v is an introducer. If so, stash it and continue.
417
+ if (auto scopeIntroducer = BorrowScopeIntroducingValue::get (value)) {
418
+ out.push_back (*scopeIntroducer);
419
+ continue ;
420
+ }
421
+
422
+ // If v produces .none ownership, then we can ignore it. It is important
423
+ // that we put this before checking for guaranteed forwarding instructions,
424
+ // since we want to ignore guaranteed forwarding instructions that in this
425
+ // specific case produce a .none value.
426
+ if (value.getOwnershipKind () == ValueOwnershipKind::None)
427
+ continue ;
428
+
429
+ // Otherwise if v is an ownership forwarding value, add its defining
430
+ // instruction
431
+ if (isGuaranteedForwardingValue (value)) {
432
+ if (auto *i = value->getDefiningInstruction ()) {
433
+ llvm::copy (i->getOperandValues (true /* skip type dependent ops*/ ),
434
+ std::back_inserter (worklist));
435
+ continue ;
436
+ }
437
+
438
+ // Otherwise, we should have a block argument that is defined by a single
439
+ // predecessor terminator.
440
+ auto *arg = cast<SILPhiArgument>(value);
441
+ auto *termInst = arg->getSingleTerminator ();
442
+ assert (termInst && termInst->isTransformationTerminator ());
443
+ assert (termInst->getNumOperands () == 1 &&
444
+ " Transforming terminators should always have a single operand" );
445
+ worklist.push_back (termInst->getAllOperands ()[0 ].get ());
446
+ continue ;
447
+ }
448
+
449
+ // Otherwise, this is an introducer we do not understand. Bail and return
450
+ // false.
451
+ return false ;
452
+ }
453
+
454
+ return true ;
455
+ }
456
+
457
+ Optional<BorrowScopeIntroducingValue>
458
+ swift::getSingleBorrowIntroducingValue (SILValue inputValue) {
459
+ if (inputValue.getOwnershipKind () != ValueOwnershipKind::Guaranteed)
460
+ return None;
461
+
462
+ SILValue currentValue = inputValue;
463
+ while (true ) {
464
+ // First check if our initial value is an introducer. If we have one, just
465
+ // return it.
466
+ if (auto scopeIntroducer = BorrowScopeIntroducingValue::get (currentValue)) {
467
+ return scopeIntroducer;
468
+ }
469
+
470
+ // Otherwise if v is an ownership forwarding value, add its defining
471
+ // instruction
472
+ if (isGuaranteedForwardingValue (currentValue)) {
473
+ if (auto *i = currentValue->getDefiningInstruction ()) {
474
+ auto instOps = i->getOperandValues (true /* ignore type dependent ops*/ );
475
+ // If we have multiple incoming values, return .None. We can't handle
476
+ // this.
477
+ auto begin = instOps.begin ();
478
+ if (std::next (begin) != instOps.end ()) {
479
+ return None;
480
+ }
481
+ // Otherwise, set currentOp to the single operand and continue.
482
+ currentValue = *begin;
483
+ continue ;
484
+ }
485
+
486
+ // Otherwise, we should have a block argument that is defined by a single
487
+ // predecessor terminator.
488
+ auto *arg = cast<SILPhiArgument>(currentValue);
489
+ auto *termInst = arg->getSingleTerminator ();
490
+ assert (termInst && termInst->isTransformationTerminator ());
491
+ assert (termInst->getNumOperands () == 1 &&
492
+ " Transformation terminators should only have single operands" );
493
+ currentValue = termInst->getAllOperands ()[0 ].get ();
494
+ continue ;
495
+ }
496
+
497
+ // Otherwise, this is an introducer we do not understand. Bail and return
498
+ // None.
499
+ return None;
500
+ }
501
+
502
+ llvm_unreachable (" Should never hit this" );
503
+ }
0 commit comments