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