@@ -507,6 +507,7 @@ Optional<BorrowedValue> getSingleBorrowIntroducingValue(SILValue inputValue);
507
507
class InteriorPointerOperandKind {
508
508
public:
509
509
enum Kind : uint8_t {
510
+ Invalid=0 ,
510
511
RefElementAddr,
511
512
RefTailAddr,
512
513
OpenExistentialBox,
@@ -518,18 +519,39 @@ class InteriorPointerOperandKind {
518
519
public:
519
520
InteriorPointerOperandKind (Kind newValue) : value(newValue) {}
520
521
521
- operator Kind () const { return value; }
522
+ operator Kind () const {
523
+ assert (isValid ());
524
+ return value;
525
+ }
526
+
527
+ bool isValid () const { return value != Kind::Invalid; }
522
528
523
- static Optional< InteriorPointerOperandKind> get (Operand *use) {
529
+ static InteriorPointerOperandKind get (Operand *use) {
524
530
switch (use->getUser ()->getKind ()) {
525
531
default :
526
- return None ;
532
+ return Kind::Invalid ;
527
533
case SILInstructionKind::RefElementAddrInst:
528
- return InteriorPointerOperandKind ( RefElementAddr) ;
534
+ return Kind:: RefElementAddr;
529
535
case SILInstructionKind::RefTailAddrInst:
530
- return InteriorPointerOperandKind ( RefTailAddr) ;
536
+ return Kind:: RefTailAddr;
531
537
case SILInstructionKind::OpenExistentialBoxInst:
532
- return InteriorPointerOperandKind (OpenExistentialBox);
538
+ return Kind::OpenExistentialBox;
539
+ }
540
+ }
541
+
542
+ // / Given a \p value that is a result of an instruction with an interior
543
+ // / pointer operand, return the interior pointer operand kind that would be
544
+ // / appropriate for that operand.
545
+ static InteriorPointerOperandKind inferFromResult (SILValue value) {
546
+ switch (value->getKind ()) {
547
+ default :
548
+ return Kind::Invalid;
549
+ case ValueKind::RefElementAddrInst:
550
+ return Kind::RefElementAddr;
551
+ case ValueKind::RefTailAddrInst:
552
+ return Kind::RefTailAddr;
553
+ case ValueKind::OpenExistentialBoxInst:
554
+ return Kind::OpenExistentialBox;
533
555
}
534
556
}
535
557
@@ -546,14 +568,42 @@ struct InteriorPointerOperand {
546
568
InteriorPointerOperandKind kind;
547
569
548
570
InteriorPointerOperand (Operand *op)
549
- : operand(op), kind(*InteriorPointerOperandKind::get (op)) {}
571
+ : operand(op), kind(InteriorPointerOperandKind::get(op)) {
572
+ assert (kind.isValid ());
573
+ }
550
574
551
- // / If value is a borrow introducer return it after doing some checks.
575
+ // / If \p op has a user that is an interior pointer, return a valid
576
+ // / value. Otherwise, return None.
552
577
static Optional<InteriorPointerOperand> get (Operand *op) {
553
578
auto kind = InteriorPointerOperandKind::get (op);
554
579
if (!kind)
555
580
return None;
556
- return InteriorPointerOperand (op, *kind);
581
+ return InteriorPointerOperand (op, kind);
582
+ }
583
+
584
+ // / If \p val is a result of an instruction that is an interior pointer,
585
+ // / return an interor pointer operand based off of the base value operand of
586
+ // / the instruction.
587
+ static Optional<InteriorPointerOperand>
588
+ inferFromResult (SILValue resultValue) {
589
+ auto kind = InteriorPointerOperandKind::inferFromResult (resultValue);
590
+
591
+ // NOTE: We use an exhaustive switch here to allow for further interior
592
+ // pointer operand having instructions to make the interior pointer
593
+ // operand's argument index arbitrary.
594
+ switch (kind) {
595
+ case InteriorPointerOperandKind::Invalid:
596
+ // We do not have a valid instruction, so return None.
597
+ return None;
598
+ case InteriorPointerOperandKind::RefElementAddr:
599
+ case InteriorPointerOperandKind::RefTailAddr:
600
+ case InteriorPointerOperandKind::OpenExistentialBox: {
601
+ // Ok, we have a valid instruction. Return the relevant operand.
602
+ auto *op =
603
+ &cast<SingleValueInstruction>(resultValue)->getAllOperands ()[0 ];
604
+ return InteriorPointerOperand (op, kind);
605
+ }
606
+ }
557
607
}
558
608
559
609
// / Return the end scope of all borrow introducers of the parent value of this
@@ -573,6 +623,8 @@ struct InteriorPointerOperand {
573
623
574
624
SILValue getProjectedAddress () const {
575
625
switch (kind) {
626
+ case InteriorPointerOperandKind::Invalid:
627
+ llvm_unreachable (" Calling method on invalid?!" );
576
628
case InteriorPointerOperandKind::RefElementAddr:
577
629
return cast<RefElementAddrInst>(operand->getUser ());
578
630
case InteriorPointerOperandKind::RefTailAddr:
0 commit comments